diff libmpcodecs/vd_qt8bps.c @ 10712:03b410c39759

Quicktime 8BPS decoder
author rtognimp
date Thu, 28 Aug 2003 21:23:40 +0000
parents
children 6193f96a04d5
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpcodecs/vd_qt8bps.c	Thu Aug 28 21:23:40 2003 +0000
@@ -0,0 +1,236 @@
+/*
+ *
+ * QuickTime 8BPS decoder for Mplayer
+ * (c) 2003 Roberto Togni
+ *
+ * Fourcc: 8BPS
+ *
+ * Supports 8bpp (paletted), 24bpp and 32bpp (4th plane ignored)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "bswap.h"
+
+#include "mp_msg.h"
+
+#include "vd_internal.h"
+
+
+static vd_info_t info = {
+  "8BPS Video decoder",
+  "qt8bps",
+  "Roberto Togni",
+  "Roberto Togni",
+  "native codec"
+};
+
+LIBVD_EXTERN(qt8bps)
+
+
+/*
+ * Decoder context
+ */
+typedef struct {
+  unsigned char planes;
+  unsigned char planemap[4];
+  unsigned char *palette;
+} qt8bps_context_t;
+
+
+/*
+ * Internal function prototypes
+ */
+
+
+// to set/get/query special features/parameters
+static int control(sh_video_t *sh,int cmd,void* arg,...)
+{
+  qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
+
+  if (cmd == VDCTRL_QUERY_FORMAT)
+    switch (hc->planes) {
+      case 1:
+        if (*((int*)arg) == IMGFMT_BGR8)
+          return CONTROL_TRUE;
+        else
+          return CONTROL_FALSE;
+        break;
+      case 3:
+      case 4:
+        if ((*((int*)arg) == IMGFMT_BGR24) || (*((int*)arg) == IMGFMT_BGR32))
+          return CONTROL_TRUE;
+        else
+          return CONTROL_FALSE;
+        break;
+      default:
+        return CONTROL_FALSE;
+    }
+
+  return CONTROL_UNKNOWN;
+}
+
+
+/*
+ *
+ * Init 8BPS decoder
+ *
+ */
+static int init(sh_video_t *sh)
+{
+  int vo_ret; // Video output init ret value
+  qt8bps_context_t *hc; // Decoder context
+  BITMAPINFOHEADER *bih = sh->bih;
+  int i;
+  unsigned char *psrc, *pdest;
+
+  if ((hc = malloc(sizeof(qt8bps_context_t))) == NULL) {
+    mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate memory for 8BPS decoder context.\n");
+    return 0;
+  }
+
+  sh->context = (void *)hc;
+  hc->palette = NULL;
+
+  switch (bih->biBitCount) {
+    case 8:
+      hc->planes = 1;
+      hc->planemap[0] = 0; // 1st plane is palette indexes
+	    if (bih->biSize > sizeof(BITMAPINFOHEADER)) {
+        psrc = (unsigned char*)bih + sizeof(BITMAPINFOHEADER);
+        pdest = hc->palette = (unsigned char *)malloc(256*3);
+        for (i = 0; i < 256; i++) {
+          *pdest++ = *psrc++;
+          *pdest++ = *psrc++;
+          *pdest++ = *psrc++;
+          psrc++;
+        }
+	    }
+      break;
+    case 24:
+      hc->planes = 3;
+      hc->planemap[0] = 2; // 1st plane is red
+      hc->planemap[1] = 1; // 2nd plane is green
+      hc->planemap[2] = 0; // 3rd plane is blue
+      break;
+    case 32:
+      hc->planes = 4;
+      hc->planemap[0] = 2; // 1st plane is red
+      hc->planemap[1] = 1; // 2nd plane is green
+      hc->planemap[2] = 0; // 3rd plane is blue
+      hc->planemap[3] = 3; // 4th plane is alpha???
+      mp_msg(MSGT_DECVIDEO, MSGL_WARN, "[8BPS] Ignoring 4th (alpha?) plane.\n");
+      break;
+    default:
+    mp_msg(MSGT_DECVIDEO, MSGL_ERR, "[8BPS] Unsupported color depth: %u.\n", bih->biBitCount);
+    return 0;    
+  }
+
+  /*
+   * Initialize video output device
+   */
+  vo_ret = mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24);
+
+  return vo_ret;
+}
+
+
+
+
+/*
+ *
+ * Uninit 8BPS decoder
+ *
+ */
+static void uninit(sh_video_t *sh)
+{
+  qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
+
+  if (sh->context) {
+    if (hc->palette)
+      free (hc->palette);
+    free(sh->context);
+  }
+}
+
+
+
+/*
+ *
+ * Decode a frame
+ *
+ */
+static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
+{
+  mp_image_t* mpi;
+  unsigned char *encoded = (unsigned char *)data;
+  qt8bps_context_t *hc = (qt8bps_context_t *) sh->context; // Decoder context
+  unsigned char *outptr, *pixptr;
+  unsigned int height = sh->disp_h; // Real image height
+  unsigned int dlen, p, row;
+  unsigned char *lp, *dp;
+  unsigned char count;
+  unsigned int px_inc;
+  unsigned int planes = hc->planes;
+  unsigned char *planemap = hc->planemap;
+  
+  
+  // Skipped frame
+  if(len <= 0)
+    return NULL;
+
+  /* Get output image buffer */
+  mpi=mpcodecs_get_image(sh, MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE, sh->disp_w, sh->disp_h);
+  if (!mpi) {
+    mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Can't allocate mpi image for 8BPS codec.\n");
+    return NULL;
+  }
+
+  outptr = mpi->planes[0]; // Output image pointer
+  px_inc = mpi->bpp/8;
+
+  /* Set data pointer after line lengths */
+  dp = encoded + hc->planes*(height << 1);
+
+  /* Ignore alpha plane, don't know what to do with it */
+  if (planes == 4)
+    planes--;
+
+  for (p = 0; p < planes; p++) {
+    /* Lines length pointer for this plane */
+    lp = encoded + p*(height << 1);
+
+    /* Decode a plane */
+    for(row = 0; row < height; row++) {
+      pixptr = outptr + row * mpi->stride[0] + planemap[p];
+      dlen = be2me_16(*(unsigned short *)(lp+row*2));
+      /* Decode a row of this plane */
+      while(dlen > 0) {
+        if ((count = *dp++) <= 127) {
+          count++;
+          dlen -= count + 1;
+          while(count--) {
+            *pixptr = *dp++;
+            pixptr += px_inc;
+          }
+        } else {
+          count = 257 - count;
+          while(count--) {
+            *pixptr = *dp;
+            pixptr += px_inc;
+          }
+          dp++;
+          dlen -= 2;
+        }
+      }
+    }
+  }
+
+  if (hc->palette)
+    mpi->planes[1] = hc->palette;
+
+  return mpi;
+}