changeset 9534:87e03d96a4cd

add support for sgi files to mencoder patch by (Todd Kirby <slapcat at pacbell dot net>)
author michael
date Wed, 05 Mar 2003 10:38:56 +0000
parents 9c596857cbe0
children aa0dd1f998d9
files etc/codecs.conf libmpcodecs/Makefile libmpcodecs/vd.c libmpcodecs/vd_sgi.c libmpdemux/demux_mf.c
diffstat 5 files changed, 342 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/etc/codecs.conf	Wed Mar 05 10:28:32 2003 +0000
+++ b/etc/codecs.conf	Wed Mar 05 10:38:56 2003 +0000
@@ -68,6 +68,15 @@
   driver mtga
   out BGR32,BGR24
 
+videocodec sgi
+  info "SGI images decoder"
+  status working
+  comment "SGI1 is an internal MPlayer FOURCC"
+  fourcc SGI1
+  driver sgi
+  out BGR24
+
+
 videocodec fli
   info "Autodesk FLI/FLC Animation"
   status working
--- a/libmpcodecs/Makefile	Wed Mar 05 10:28:32 2003 +0000
+++ b/libmpcodecs/Makefile	Wed Mar 05 10:38:56 2003 +0000
@@ -10,7 +10,7 @@
 AUDIO_SRCS=dec_audio.c ad.c $(AUDIO_SRCS_LIB) $(AUDIO_SRCS_NAT) $(AUDIO_SRCS_OPT)
 
 VIDEO_SRCS_LIB=vd_libmpeg2.c vd_nuv.c vd_lzo.c
-VIDEO_SRCS_NAT=vd_null.c vd_cinepak.c vd_qtrpza.c vd_raw.c vd_msvidc.c vd_fli.c vd_qtrle.c vd_qtsmc.c vd_roqvideo.c vd_cyuv.c vd_msrle.c vd_huffyuv.c vd_mpegpes.c vd_svq1.c vd_lcl.c vd_mtga.c
+VIDEO_SRCS_NAT=vd_null.c vd_cinepak.c vd_qtrpza.c vd_raw.c vd_msvidc.c vd_fli.c vd_qtrle.c vd_qtsmc.c vd_roqvideo.c vd_cyuv.c vd_msrle.c vd_huffyuv.c vd_mpegpes.c vd_svq1.c vd_lcl.c vd_mtga.c vd_sgi.c
 VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_xanim.c vd_xvid.c vd_libdv.c vd_qtvideo.c
 VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
 
--- a/libmpcodecs/vd.c	Wed Mar 05 10:28:32 2003 +0000
+++ b/libmpcodecs/vd.c	Wed Mar 05 10:38:56 2003 +0000
@@ -48,6 +48,7 @@
 extern vd_functions_t mpcodecs_vd_mpng;
 extern vd_functions_t mpcodecs_vd_ijpg;
 extern vd_functions_t mpcodecs_vd_mtga;
+extern vd_functions_t mpcodecs_vd_sgi;
 extern vd_functions_t mpcodecs_vd_libmpeg2;
 extern vd_functions_t mpcodecs_vd_huffyuv;
 extern vd_functions_t mpcodecs_vd_mpegpes;
@@ -100,6 +101,7 @@
 	&mpcodecs_vd_ijpg,
 #endif
 	&mpcodecs_vd_mtga,
+	&mpcodecs_vd_sgi,
 #ifdef USE_LIBMPEG2
         &mpcodecs_vd_libmpeg2,
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpcodecs/vd_sgi.c	Wed Mar 05 10:38:56 2003 +0000
@@ -0,0 +1,327 @@
+/*
+ * author: Todd Kirby <slapcat@pacbell.net>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "bswap.h"
+#include "vd_internal.h"
+
+#define SGI_HEADER_LEN 512
+#define SGI_MAGIC 474
+
+#define SGI_GRAYSCALE_IMAGE 1
+#define SGI_RGB_IMAGE 3
+#define SGI_RGBA_IMAGE 4
+
+#define OUT_PIXEL_STRIDE 3 /* RGB */
+
+
+static vd_info_t info =
+{
+  "SGI Image decoder",
+  "sgi",
+  "Todd Kirby",
+  "Todd Kirby",
+  ""
+};
+
+LIBVD_EXTERN(sgi)
+
+typedef struct {
+  short magic;
+  char rle;
+  char bytes_per_channel;
+  unsigned short dimension;
+  unsigned short xsize;
+  unsigned short ysize;
+  unsigned short zsize;
+} SGIInfo;
+
+static unsigned int outfmt = IMGFMT_BGR24;
+
+static unsigned short last_x = -1;
+static unsigned short last_y = -1;
+
+
+/* to set/get/query special features/parameters */
+static int
+control(sh_video_t* sh, int cmd, void *arg, ...)
+{ 
+  switch (cmd)
+  {
+    case VDCTRL_QUERY_FORMAT:
+      if (*((unsigned int *) arg) == outfmt) {
+        return CONTROL_TRUE;
+      }
+      return CONTROL_FALSE;
+  }
+  return CONTROL_UNKNOWN;
+}
+
+
+/* init driver */
+static int
+init(sh_video_t *sh)
+{
+  sh->context = (SGIInfo *) calloc(1, sizeof(SGIInfo));
+  last_x = -1;
+
+  return 1;
+}
+
+
+/* uninit driver */
+static void
+uninit(sh_video_t *sh)
+{
+  SGIInfo	*info = sh->context;
+  free(info);
+}
+
+
+/* expand an rle row into a channel */
+static void
+expandrow(unsigned char *optr, unsigned char *iptr, int chan_offset)
+{
+  unsigned char pixel, count;
+  optr += chan_offset;
+  
+  while (1) {
+    pixel = *iptr++;
+    
+    if (!(count = (pixel & 0x7f))) {
+      return;
+    }
+    if(pixel & 0x80) {
+      while (count--) {
+        *optr = *iptr;
+        optr += OUT_PIXEL_STRIDE;
+        iptr++;
+      }
+    } else {
+      pixel = *iptr++;
+      
+      while (count--) {
+        *optr = pixel;
+        optr += OUT_PIXEL_STRIDE;
+      }
+    }
+  }
+}
+
+
+/* expand an rle row into all 3 channels.
+   a separate function for grayscale so we don't slow down the 
+   more common case rgb function with a bunch of ifs. */
+static void
+expandrow_gs(unsigned char *optr, unsigned char *iptr)
+{
+  unsigned char pixel, count;
+  
+  while (1) {
+    pixel = *iptr++;
+    
+    if (!(count = (pixel & 0x7f))) {
+      return;
+    }
+    if(pixel & 0x80) {
+      while (count--) {
+        optr[0] = *iptr;
+        optr[1] = *iptr;
+        optr[2] = *iptr;
+        optr += OUT_PIXEL_STRIDE;
+        iptr++;
+      }
+    } else {
+      pixel = *iptr++;
+      
+      while (count--) {
+        optr[0] = pixel;
+        optr[1] = pixel;
+        optr[2] = pixel;
+        optr += OUT_PIXEL_STRIDE;
+      }
+    }
+  }
+}
+
+
+/* decode a run length encoded sgi image */
+static void
+decode_rle_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
+{
+  unsigned char *rle_data, *dest_row;
+  unsigned long *starttab;
+  int y, z, xsize, ysize, zsize, chan_offset;
+  long start_offset;
+  
+  xsize = info->xsize;
+  ysize = info->ysize;
+  zsize = info->zsize;
+
+  /* rle offset table is right after the header */
+  starttab = (long*)(data + SGI_HEADER_LEN); 
+  
+   for (z = 0; z < zsize; z++) {
+
+     /* set chan_offset so RGB ends up BGR */
+     chan_offset = (zsize - 1) - z;
+     
+     /* The origin for SGI images is the lower-left corner
+        so read scan lines from bottom to top */
+     for (y = ysize - 1; y >= 0; y--) {
+       dest_row = mpi->planes[0] + mpi->stride[0] * (ysize - 1 - y);
+    
+      /* set start of next run (offsets are from start of header) */
+      start_offset = be2me_32(*(unsigned long*) &starttab[y + z * ysize]);
+      
+      rle_data = &data[start_offset];
+    
+      if(info->zsize == SGI_GRAYSCALE_IMAGE) {
+        expandrow_gs(dest_row, rle_data);
+      } else {
+        expandrow(dest_row, rle_data, chan_offset);
+      }
+    }
+  }
+}
+
+  
+/* decode an sgi image */
+static void
+decode_uncompressed_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
+{
+  unsigned char *src_row, *dest_row;
+  int x, y, z, xsize, ysize, zsize, chan_offset;
+  
+  xsize = info->xsize;
+  ysize = info->ysize;
+  zsize = info->zsize;
+  
+  /* skip header */ 
+  data += SGI_HEADER_LEN;
+  
+  for (z = 0; z < zsize; z++) {
+
+    /* set row ptr to start of current plane */
+    src_row = data + (xsize * ysize * z);
+
+    /* set chan_offset for RGB -> BGR */
+    chan_offset = (zsize - 1) - z;
+    
+    /* the origin for SGI images is the lower-left corner  
+       so read scan lines from bottom to top. */
+    for (y = ysize - 1; y >= 0; y--) {
+      dest_row = mpi->planes[0] + mpi->stride[0] * y;
+      for (x = 0; x < xsize; x++) {
+        
+        /* we only do 24 bit output so promote 8 bit pixels to 24 */
+        if (zsize == SGI_GRAYSCALE_IMAGE) {
+          /* write greyscale value into all channels */
+          dest_row[0] = src_row[x];
+          dest_row[1] = src_row[x];
+          dest_row[2] = src_row[x];
+        } else {
+          dest_row[chan_offset] = src_row[x];
+        }
+        
+        dest_row += OUT_PIXEL_STRIDE;
+      }
+
+      /* move to next row of the current source plane */
+      src_row += xsize;
+    }
+  }
+}
+
+
+/* read sgi header fields */
+static void
+read_sgi_header(unsigned char *buf, SGIInfo *info)
+{
+  /* sgi data is always stored in big endian byte order */
+  info->magic = be2me_16(*(unsigned short *) &buf[0]);     
+  info->rle = buf[2];
+  info->bytes_per_channel = buf[3];
+  info->dimension = be2me_16(*(unsigned short *) &buf[4]);     
+  info->xsize = be2me_16(*(unsigned short *) &buf[6]);     
+  info->ysize = be2me_16(*(unsigned short *) &buf[8]);     
+  info->zsize = be2me_16(*(unsigned short *) &buf[10]);     
+}
+
+
+/* decode a frame */
+static
+mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
+{
+  SGIInfo *info = sh->context;
+  unsigned char *data = raw;
+  mp_image_t *mpi;
+
+  if (len <= 0) {
+    return NULL; /* skip frame */
+  }
+    
+  read_sgi_header(data, info); 
+  
+  /* make sure this is an SGI image file */
+  if (info->magic != SGI_MAGIC) {
+    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Bad magic number in image.\n");
+    return NULL;
+  }
+
+  /* check image depth */
+  if (info->bytes_per_channel != 1) {
+    mp_msg(MSGT_DECVIDEO, MSGL_INFO, 
+        "Unsupported bytes per channel value %i.\n", info->bytes_per_channel);
+    return NULL;
+  }
+
+  /* check image dimension */
+  if (info->dimension != 2 && info->dimension != 3) {
+    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image dimension %i.\n", 
+        info->dimension);
+    return NULL;
+  }
+
+  /* change rgba images to rgb so alpha channel will be ignored */ 
+  if (info->zsize == SGI_RGBA_IMAGE) {
+    info->zsize = SGI_RGB_IMAGE;
+  }
+
+  /* check image depth */
+  if (info->zsize != SGI_RGB_IMAGE && info->zsize != SGI_GRAYSCALE_IMAGE) {
+    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image depth.\n");
+    return NULL;
+  }
+  
+  /* (re)init libvo if image size is changed */
+  if (last_x != info->xsize || last_y != info->ysize)
+  {
+    last_x = info->xsize;
+    last_y = info->ysize;
+    
+    if (!mpcodecs_config_vo(sh, info->xsize, info->ysize, outfmt)) {
+      mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Config vo failed:\n");
+      return NULL;
+    }
+  }
+   
+  if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, 
+          info->xsize, info->ysize))) {
+    return NULL;
+  }
+ 
+  if (info->rle) {
+    decode_rle_sgi(info, data, mpi);
+  } else {
+    decode_uncompressed_sgi(info, data, mpi);
+  }
+  
+  return mpi;
+}
+
--- a/libmpdemux/demux_mf.c	Wed Mar 05 10:28:32 2003 +0000
+++ b/libmpdemux/demux_mf.c	Wed Mar 05 10:38:56 2003 +0000
@@ -98,7 +98,9 @@
      if ( !strcasecmp( mf_type,"png" )) sh_video->format = mmioFOURCC('M', 'P', 'N', 'G' );
   else
      if ( !strcasecmp( mf_type,"tga" )) sh_video->format = mmioFOURCC('M', 'T', 'G', 'A' );
-  else { mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] unknow input file type.\n" ); free( mf ); return NULL; }
+   else
+     if (!strcasecmp( mf_type,"sgi" )) sh_video->format = mmioFOURCC('S', 'G', 'I', '1');
+  else { mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] unknown input file type.\n" ); free( mf ); return NULL; }
 
   sh_video->disp_w = mf_w;
   sh_video->disp_h = mf_h;