mirror of https://github.com/mpv-player/mpv
add support for sgi files to mencoder patch by (Todd Kirby <slapcat at pacbell dot net>)
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9535 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
1815f7c64e
commit
b749836b08
|
@ -68,6 +68,15 @@ videocodec mtga
|
||||||
driver mtga
|
driver mtga
|
||||||
out BGR32,BGR24
|
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
|
videocodec fli
|
||||||
info "Autodesk FLI/FLC Animation"
|
info "Autodesk FLI/FLC Animation"
|
||||||
status working
|
status working
|
||||||
|
|
|
@ -10,7 +10,7 @@ AUDIO_SRCS_OPT=ad_acm.c ad_dshow.c ad_dmo.c ad_qtaudio.c ad_ffmpeg.c ad_faad.c a
|
||||||
AUDIO_SRCS=dec_audio.c ad.c $(AUDIO_SRCS_LIB) $(AUDIO_SRCS_NAT) $(AUDIO_SRCS_OPT)
|
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_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_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)
|
VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ extern vd_functions_t mpcodecs_vd_nuv;
|
||||||
extern vd_functions_t mpcodecs_vd_mpng;
|
extern vd_functions_t mpcodecs_vd_mpng;
|
||||||
extern vd_functions_t mpcodecs_vd_ijpg;
|
extern vd_functions_t mpcodecs_vd_ijpg;
|
||||||
extern vd_functions_t mpcodecs_vd_mtga;
|
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_libmpeg2;
|
||||||
extern vd_functions_t mpcodecs_vd_huffyuv;
|
extern vd_functions_t mpcodecs_vd_huffyuv;
|
||||||
extern vd_functions_t mpcodecs_vd_mpegpes;
|
extern vd_functions_t mpcodecs_vd_mpegpes;
|
||||||
|
@ -100,6 +101,7 @@ vd_functions_t* mpcodecs_vd_drivers[] = {
|
||||||
&mpcodecs_vd_ijpg,
|
&mpcodecs_vd_ijpg,
|
||||||
#endif
|
#endif
|
||||||
&mpcodecs_vd_mtga,
|
&mpcodecs_vd_mtga,
|
||||||
|
&mpcodecs_vd_sgi,
|
||||||
#ifdef USE_LIBMPEG2
|
#ifdef USE_LIBMPEG2
|
||||||
&mpcodecs_vd_libmpeg2,
|
&mpcodecs_vd_libmpeg2,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -98,7 +98,9 @@ demuxer_t* demux_open_mf(demuxer_t* demuxer){
|
||||||
if ( !strcasecmp( mf_type,"png" )) sh_video->format = mmioFOURCC('M', 'P', 'N', 'G' );
|
if ( !strcasecmp( mf_type,"png" )) sh_video->format = mmioFOURCC('M', 'P', 'N', 'G' );
|
||||||
else
|
else
|
||||||
if ( !strcasecmp( mf_type,"tga" )) sh_video->format = mmioFOURCC('M', 'T', 'G', 'A' );
|
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_w = mf_w;
|
||||||
sh_video->disp_h = mf_h;
|
sh_video->disp_h = mf_h;
|
||||||
|
|
Loading…
Reference in New Issue