diff options
Diffstat (limited to 'src/libspudec')
-rw-r--r-- | src/libspudec/Makefile.am | 36 | ||||
-rw-r--r-- | src/libspudec/spu.c | 399 | ||||
-rw-r--r-- | src/libspudec/spu.h | 67 | ||||
-rw-r--r-- | src/libspudec/spu_decoder_api.h | 69 | ||||
-rw-r--r-- | src/libspudec/xine_decoder.c | 184 |
5 files changed, 750 insertions, 5 deletions
diff --git a/src/libspudec/Makefile.am b/src/libspudec/Makefile.am index c96adda1d..11d4cb535 100644 --- a/src/libspudec/Makefile.am +++ b/src/libspudec/Makefile.am @@ -1,12 +1,38 @@ -CFLAGS = @BUILD_LIB_STATIC@ @GLOBAL_CFLAGS@ +CFLAGS = @GLOBAL_CFLAGS@ -EXTRA_DIST = +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic -noinst_LTLIBRARIES = libspudec.la +libdir = $(XINE_PLUGINDIR) -libspudec_la_SOURCES = spudec.c spudec.h +lib_LTLIBRARIES = xineplug_decode_spu.la + +xineplug_decode_spu_la_SOURCES = spu.c xine_decoder.c +xineplug_decode_spu_la_LDFLAGS = -avoid-version -module + +noinst_HEADERS = spu.h spu_decoder_api.h + +## +## Install header files (default=$includedir/xine) +## +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(includedir)/xine + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p; \ + done + + +## +## Remove them +## +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(include_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(includedir)/xine/$$p; \ + done -noinst_HEADERS = spudec.h debug: $(MAKE) CFLAGS="$(DEBUG_CFLAGS)" diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c new file mode 100644 index 000000000..13d9c92c8 --- /dev/null +++ b/src/libspudec/spu.c @@ -0,0 +1,399 @@ +/***** +* +* This file is part of the OMS program. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#define DENT_TEST + +/* + * subpic_decode.c - converts DVD subtitles to an XPM image + * + * Mostly based on hard work by: + * + * Copyright (C) 2000 Samuel Hocevar <sam@via.ecp.fr> + * and Michel Lespinasse <walken@via.ecp.fr> + * + * Lots of rearranging by: + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * Thomas Mirlacher <dent@cosy.sbg.ac.at> + * implemented reassembling + * cleaner implementation of SPU are saving + * overlaying (proof of concept for now) + * ... and yes, it works now with oms + * added tranparency (provided by the SPU hdr) + * changed structures for easy porting to MGAs DVD mode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> +#include <malloc.h> +#include <sys/stat.h> +#include <fcntl.h> + +//#include <oms/plugin/output_video.h> // for clut_t +#include "spu.h" + +static u_int field; // which field we are currently decoding + +#define DISPLAY_INIT + +#define REASSEMBLY_START 0 +#define REASSEMBLY_MID 1 +#define REASSEMBLY_UNNEEDED 2 + +static u_int reassembly_flag = REASSEMBLY_START; + +struct reassembly_s { + uint8_t *buf; + uint8_t *buf_ptr; // actual pointer to still empty buffer + u_int buf_len; + u_int cmd_offset; +} reassembly; + +#define LOG_DEBUG 1 + +#ifdef DEBUG +#define LOG(lvl, fmt...) fprintf (stderr, fmt); +#else +#define LOG(lvl, fmt...) +#endif + + +static u_int _get_bits (u_int bits, vo_overlay_t *spu) +{ + static u_int data; + static u_int bits_left; + u_int ret = 0; + + if (!bits) { /* for realignment to next byte */ + bits_left = 0; + } + + while (bits) { + if (bits > bits_left) { + ret |= data << (bits - bits_left); + bits -= bits_left; + + data = reassembly.buf[spu->offset[field]++]; + bits_left = 8; + } else { + bits_left -= bits; + ret |= data >> (bits_left); + data &= (1 << bits_left) - 1; + bits = 0; + } + } + + return ret; +} + + +void spuInit (void) +{ +} + + +static inline void _spu_put_pixel (vo_overlay_t *spu, u_int len, uint8_t colorid) +{ + uint8_t *spu_data_ptr = &spu->data[spu->_x + spu->_y * spu->width]; + + spu->_x += len; + + memset (spu_data_ptr, spu->trans[colorid]<<4 | colorid, len); +} + + +static int _spu_next_line (vo_overlay_t *spu) +{ + _get_bits (0, spu); // byte align rle data + + spu->_x = 0; + spu->_y++; + field = (field+1) & 0x01; // Toggle fields + + if (spu->_y >= spu->height) { + LOG (LOG_DEBUG, "."); + return -1; + } + return 0; +} + + +// DENT: we need a mechanism here, when having non-linearities (like jumps, ff) + // like pass NULL pkt_data to reset reassembly + +static struct reassembly_s *_reassembly (uint8_t *pkt_data, u_int pkt_len) +{ + LOG (LOG_DEBUG, "pkt_len: %d", pkt_len); + + if (reassembly_flag == REASSEMBLY_UNNEEDED) + reassembly_flag = REASSEMBLY_START; + + if (reassembly_flag == REASSEMBLY_START) { + reassembly.buf_len = (((u_int)pkt_data[0])<<8) | pkt_data[1]; + reassembly.cmd_offset = (((u_int)pkt_data[2])<<8) | pkt_data[3]; + + LOG (LOG_DEBUG, "buf_len: %d", reassembly.buf_len); + LOG (LOG_DEBUG, "cmd_off: %d", reassembly.cmd_offset); + + // the whole spu fits into the supplied packet + if (pkt_len >= reassembly.buf_len) { + LOG (LOG_DEBUG, "0)"); + reassembly.buf = pkt_data; + reassembly_flag = REASSEMBLY_UNNEEDED; + return &reassembly; + } else { + LOG (LOG_DEBUG, "1)"); + if (!(reassembly.buf = malloc (reassembly.buf_len + 1))) { + LOG (LOG_DEBUG, "unable to alloc buffer"); + return NULL; + } + reassembly.buf_ptr = reassembly.buf; + + memcpy (reassembly.buf_ptr, pkt_data, pkt_len); + reassembly.buf_ptr += pkt_len; + reassembly_flag = REASSEMBLY_MID; + } + } else { + LOG (LOG_DEBUG, "2)"); + if ((reassembly.buf_ptr+pkt_len) > (reassembly.buf+reassembly.buf_len)) + pkt_len = reassembly.buf_len - (reassembly.buf_ptr - reassembly.buf); + + + memcpy (reassembly.buf_ptr, pkt_data, pkt_len); + reassembly.buf_ptr += pkt_len; + + if (reassembly.buf_ptr >= (reassembly.buf+reassembly.buf_len)) { + reassembly_flag = REASSEMBLY_START; + return &reassembly; + } + } + + LOG (LOG_DEBUG, "3)"); + return NULL; +} + + +#define CMD_SPU_MENU 0x00 +#define CMD_SPU_SHOW 0x01 +#define CMD_SPU_HIDE 0x02 +#define CMD_SPU_SET_PALETTE 0x03 +#define CMD_SPU_SET_ALPHA 0x04 +#define CMD_SPU_SET_SIZE 0x05 +#define CMD_SPU_SET_PXD_OFFSET 0x06 +#define CMD_SPU_EOF 0xff + +/* The time is given as an offset from the presentation time stamp + and it is measured in number of fields. If we play a NTSC movie + the time for each field is 1/(2*29.97) seconds. */ +#define TIME_UNIT 1000*1.0/(2*29.97) + +int spuParseHdr (vo_overlay_t *spu, uint8_t *pkt_data, u_int pkt_len) +{ + struct reassembly_s *reassembly; + uint8_t *buf; + u_int DCSQ_offset, prev_DCSQ_offset = -1; + + if (!(reassembly = _reassembly (pkt_data, pkt_len))) + return -1; + + buf = reassembly->buf; + DCSQ_offset = reassembly->cmd_offset; + + while (DCSQ_offset != prev_DCSQ_offset) { /* Display Control Sequences */ + u_int i = DCSQ_offset; + + spu->duration = /* PTS + */ ((buf[i] << 8) + buf[i+1]) * TIME_UNIT; + LOG (LOG_DEBUG, "time = %d ms", spu->duration); + i += 2; + + prev_DCSQ_offset = DCSQ_offset; + DCSQ_offset = (buf[i] << 8) + buf[i+1]; + i += 2; + + while (buf[i] != CMD_SPU_EOF) { /* Command Sequence */ + switch (buf[i]) { + case CMD_SPU_SHOW: /* show subpicture */ + LOG (LOG_DEBUG, "\tshow subpicture"); + i++; + break; + + case CMD_SPU_HIDE: /* hide subpicture */ + LOG (LOG_DEBUG, "\thide subpicture"); + i++; + break; + + case CMD_SPU_SET_PALETTE: { /* CLUT */ + spu_clut_t *clut = (spu_clut_t *) &buf[i+1]; + + spu->clut[0] = clut->entry0; + spu->clut[1] = clut->entry1; + spu->clut[2] = clut->entry2; + spu->clut[3] = clut->entry3; + LOG (LOG_DEBUG, "\tclut [%d %d %d %d]", + spu->clut[0], spu->clut[1], spu->clut[2], spu->clut[3]); + i += 3; + break; + } + case CMD_SPU_SET_ALPHA: { /* transparency palette */ +#ifndef DENT_TEST + spu_clut_t *trans = (spu_clut_t *) &buf[i+1]; + + spu->trans[3] = trans->entry0; + spu->trans[2] = trans->entry1; + spu->trans[1] = trans->entry2; + spu->trans[0] = trans->entry3; +#else + spu->trans[0] = 0; + spu->trans[1] = spu->trans[2] = spu->trans[3] = 15; +#endif + LOG (LOG_DEBUG, "\ttrans [%d %d %d %d]\n", + spu->trans[0], spu->trans[1], spu->trans[2], spu->trans[3]); + i += 3; + break; + } + + case CMD_SPU_SET_SIZE: /* image coordinates */ + spu->x = (buf[i+1] << 4) | + (buf[i+2] >> 4); + spu->width = (((buf[i+2] & 0x0f) << 8) | + buf[i+3]) - spu->x + 1; /* 1-720 */ + + spu->y = (buf[i+4] << 4) | + (buf[i+5] >> 4); + spu->height = (((buf[i+5] & 0x0f) << 8) + | buf[i+6]) - spu->y + 1; /* 1-576 */ + + spu->data = (uint8_t *) malloc (spu->width * spu->height * sizeof (uint8_t)); + /* Private stuff */ + spu->_x = spu->_y = 0; + LOG (LOG_DEBUG, "\tx = %d y = %d width = %d height = %d", + spu->x, spu->y, spu->width, spu->height); + i += 7; + break; + + case CMD_SPU_SET_PXD_OFFSET: /* image 1 / image 2 offsets */ + spu->offset[0] = (((u_int)buf[i+1]) << 8) | buf[i+2]; + spu->offset[1] = (((u_int)buf[i+3]) << 8) | buf[i+4]; + LOG (LOG_DEBUG, "\toffset[0] = %d offset[1] = %d", + spu->offset[0], spu->offset[1]); + i += 5; + break; + + case CMD_SPU_MENU: + /* + * hardcoded menu clut, uncomment this and comment CMD_SPU_SET_PALETTE and + * CMD_SPU_SET_ALPHA to see the menu buttons + */ +#ifdef DENT_TEST + spu->clut[0] = 0; + spu->clut[1] = 9; + spu->clut[2] = 8; + spu->clut[3] = 12; + spu->trans[0] = 0; + spu->trans[1] = spu->trans[2] = spu->trans[3] = 15; +#endif + i++; + break; + + default: + LOG (LOG_DEBUG, "invalid sequence in control header (%.2x)", buf[i]); + i++; + break; + } + } + i++; /* lose the CMD_SPU_EOF code (no need to, really) */ + + /* Until we change the interface we parse all 'Command Sequence's + but just overwrite the data in spu. Should be a list instead. */ + } + + /* Here we should have a linked list of display commands ready to + be decoded/executed by later calling some spu???() */ + + return 0; +} + + +void spuParseData (vo_overlay_t *spu) +{ + field = 0; + _get_bits (0, spu); /* Reset/init bit code */ + + while ((spu->offset[1] < reassembly.cmd_offset)) { + u_int len; + u_int color; + u_int vlc; + + vlc = _get_bits (4, spu); + if (vlc < 0x0004) { + vlc = (vlc << 4) | _get_bits (4, spu); + if (vlc < 0x0010) { + vlc = (vlc << 4) | _get_bits (4, spu); + if (vlc < 0x0040) { + vlc = (vlc << 4) | _get_bits (4, spu); + } + } + } + + color = vlc & 0x03; + len = vlc>>2; + + /* if len == 0 -> end sequence - fill to end of line */ + len = len ? : spu->width - spu->_x; + + _spu_put_pixel (spu, len, color); + + if (spu->_x >= spu->width) + if (_spu_next_line (spu) < 0) + goto clean_up; + } + + /* Like the eof-line escape, fill the rest of the sp. with background */ + _spu_put_pixel (spu, spu->width - spu->_x, 0); + while (!_spu_next_line (spu)) { + _spu_put_pixel (spu, spu->width - spu->_x, 0); + } + + clean_up: + if (reassembly_flag != REASSEMBLY_UNNEEDED) { + LOG (LOG_DEBUG, "freeing reassembly.buf"); + free (reassembly.buf); + } + + reassembly_flag = REASSEMBLY_START; +} diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h new file mode 100644 index 000000000..844010243 --- /dev/null +++ b/src/libspudec/spu.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: spu.h,v 1.1 2001/07/04 17:10:24 uid32519 Exp $ + * + * This file was originally part of the OMS program. + * + */ + +#ifndef __SPU_H__ +#define __SPU_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <inttypes.h> +#include "video_out.h" + +#ifndef CLUT_T +#define CLUT_T +typedef struct { // CLUT == Color LookUp Table + uint8_t:8; + uint8_t y:8; + uint8_t cr:8; + uint8_t cb:8; +} __attribute__ ((packed)) clut_t; +#endif + +typedef struct spu_clut_struct { +#ifdef WORDS_BIGENDIAN + uint8_t entry0 : 4; + uint8_t entry1 : 4; + uint8_t entry2 : 4; + uint8_t entry3 : 4; +#else + uint8_t entry1 : 4; + uint8_t entry0 : 4; + uint8_t entry3 : 4; + uint8_t entry2 : 4; +#endif +} spu_clut_t; + + +void spuInit (void); +void decode_spu (u_char *data_start, u_char *data_end); +u_int buffer_spupack (u_int *length, u_char **start, u_char *end); +int spuParseHdr (vo_overlay_t *spu, u_char *pkt_data, u_int pkt_len); +void spuParseData (vo_overlay_t *spu); + +#endif diff --git a/src/libspudec/spu_decoder_api.h b/src/libspudec/spu_decoder_api.h new file mode 100644 index 000000000..4dfd2739a --- /dev/null +++ b/src/libspudec/spu_decoder_api.h @@ -0,0 +1,69 @@ +/* + * spu_decoder_api.h + * + * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, + * + */ + +#ifndef HAVE_SPU_API_H +#define HAVE_SPU_API_H + + /* + * generic xine spu decoder plugin interface + * + * for a dynamic plugin make sure you provide this function call: + * spu_decoder_t *init_spu_decoder_plugin (int iface_version, + * config_values_t *cfg); + */ + +typedef struct spu_decoder_s spu_decoder_t; + +struct spu_decoder_s { + + int interface_version; + + int (*can_handle) (spu_decoder_t *this, int buf_type); + + void (*init) (spu_decoder_t *this, vo_instance_t *video_out); + + void (*decode_data) (spu_decoder_t *this, buf_element_t *buf); + + void (*close) (spu_decoder_t *this); + + char* (*get_identifier) (void); + +}; + + + +typedef struct spudec_s spudec_t; + +struct spudec_s { + + /* + * reset spudec for a new stream + * + * clut : pointer to array of 16 cluts for palette info + */ + + void (*spudec_start) (spudec_t *this, clut_t *clut); + +}; + +#endif /* HAVE_SPUDEC_H */ diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c new file mode 100644 index 000000000..bcbcbb4ce --- /dev/null +++ b/src/libspudec/xine_decoder.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_decoder.c,v 1.1 2001/07/04 17:10:24 uid32519 Exp $ + * + * stuff needed to turn libspu into a xine decoder plugin + */ + +/* + * FIXME: libspu uses global variables (that are written to) + */ + + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "spu.h" +#include "buffer.h" +#include "xine_internal.h" + +#define FRAME_SIZE 4096 + + +typedef struct spudec_decoder_s { + spu_decoder_t spu_decoder; + + uint32_t pts; + + uint8_t frame_buffer[FRAME_SIZE]; + uint8_t *frame_ptr; + int sync_todo; + int frame_length, frame_todo; + uint16_t syncword; + + vo_instance_t *vo_out; + vo_overlay_t *spu; + int spu_caps; + int bypass_mode; + int max_num_channels; + int output_sampling_rate; + int output_open; + int output_mode; + +} spudec_decoder_t; + +int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) { + return ((buf_type & 0xFFFF0000) == BUF_SPU_PACKAGE) ; +} + + +void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) { + + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + printf("spudec_init %p\n",&vo_out); + this->vo_out = vo_out; + this->spu_caps = vo_out->get_capabilities(vo_out); + this->syncword = 0; + this->sync_todo = 6; + this->output_open = 0; + +// spu_init (); + +} + +u_int *overlay_txt (vo_overlay_t *spu, float o1) +{ + u_int x, y; + u_char tmp; + /* u_char *clr_ptr1 = (u_char *) img1; */ + u_char *clr_ptr2; + u_char *spu_data_ptr = (u_char *) spu->data; + float o; + + /* don't know why this can happen - but it does happen */ + if ((spu->width <= 0) || (spu->height <= 0) || + (spu->width > 1024) || (spu->height > 1024)) { + fprintf (stderr, "width || height out of range.\n"); + return NULL; + } + + for (y = spu->y; y < (spu->height + spu->y); y++) { + // clr_ptr1 = (u_char *) (img1 + y * 720 + spu->x); + for (x = spu->x; x < (spu->width + spu->x); x++) { + o = ((float) (*spu_data_ptr>>4) / 15.0) * o1; + //clr_ptr2 = (u_char *) &spu_clut[*spu_data_ptr&0x0f]; + *clr_ptr2 = *spu_data_ptr&0x0f; + tmp=*spu_data_ptr; + printf("%X%X",tmp&0x0f,((tmp>>4)&0x0f)); + spu_data_ptr ++; + + // printf("%d ",(*clr_ptr2++)); + // printf("%d ",(*clr_ptr2++)); + // printf("%d ",(*clr_ptr2++)); + // printf("%d \n",(*clr_ptr2++)); + } + printf("\n"); + } + + return 0; +} + +void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { + + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + + uint8_t *current = buf->content; + /* uint8_t *end = buf->content + buf->size; */ + + printf ("spudec_decode_data\n"); + + if (!this->spu) { + this->spu = this->vo_out->get_overlay (this->vo_out); + } + + /* FIXME: shouldn't happen, but get_overlay function isn't implemented yet */ + if (!this->spu) + return; + + if (!spuParseHdr (this->spu, current, buf->size)) { + spuParseData (this->spu); + printf("X=%d Y=%d w=%d h=%d\n", + this->spu->x,this->spu->y, + this->spu->width,this->spu->height); + /* overlay_txt(this->spu,1.0); ??? */ + this->spu->PTS = buf->PTS; + this->vo_out->queue_overlay (this->vo_out, this->spu); + this->spu = NULL; + } + +} + +void spudec_close (spu_decoder_t *this_gen) { + + /* spudec_decoder_t *this = (spudec_decoder_t *) this_gen; */ + +// if (this->output_open) +// this->spu_out->close (this->spu_out); + + /* close (spufile); */ +} + +static char *spudec_get_id(void) { + return "spudec"; +} + +spu_decoder_t *init_spu_decoder_plugin (int iface_version, config_values_t *cfg) { + + spudec_decoder_t *this ; + + if (iface_version != 1) + return NULL; + + this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t)); + + this->spu_decoder.interface_version = 1; + this->spu_decoder.can_handle = spudec_can_handle; + this->spu_decoder.init = spudec_init; + this->spu_decoder.decode_data = spudec_decode_data; + this->spu_decoder.close = spudec_close; + this->spu_decoder.get_identifier = spudec_get_id; + + return (spu_decoder_t *) this; +} + |