changeset 6720:180e27f21ff2

8 and 16bpp qtrle support
author alex
date Fri, 12 Jul 2002 17:49:04 +0000
parents 5291d74a60c9
children 1cd03b5da35d
files libmpcodecs/native/qtrle.c libmpcodecs/vd_qtrle.c
diffstat 2 files changed, 242 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- 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;
 }