mirror of
https://github.com/mpv-player/mpv
synced 2025-02-22 15:56:59 +00:00
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:
parent
4d25d1b683
commit
3d0493357f
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user