# HG changeset patch # User alex # Date 1026496144 0 # Node ID 180e27f21ff29d06083a332b15b8f59eee5fbbf6 # Parent 5291d74a60c96f4d4c10aa94efad28f2a7efdf4c 8 and 16bpp qtrle support diff -r 5291d74a60c9 -r 180e27f21ff2 libmpcodecs/native/qtrle.c --- a/libmpcodecs/native/qtrle.c Fri Jul 12 17:09:53 2002 +0000 +++ b/libmpcodecs/native/qtrle.c Fri Jul 12 17:49:04 2002 +0000 @@ -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 @@ { 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, diff -r 5291d74a60c9 -r 180e27f21ff2 libmpcodecs/vd_qtrle.c --- a/libmpcodecs/vd_qtrle.c Fri Jul 12 17:09:53 2002 +0000 +++ b/libmpcodecs/vd_qtrle.c Fri Jul 12 17:49:04 2002 +0000 @@ -17,27 +17,79 @@ 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; + + ctx = sh->context = malloc(sizeof(vd_qtrle_ctx)); + if (!ctx) + return(0); + memset(ctx, 0, sizeof(vd_qtrle_ctx)); - return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24); + 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 @@ // 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 @@ sh->disp_w, sh->disp_h, sh->bih->biBitCount, mpi->bpp/8); + + if (ctx->palette) + mpi->planes[1] = ctx->palette; return mpi; }