Mercurial > mplayer.hg
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;