diff options
author | uid32519 <none@none> | 2001-07-04 17:10:24 +0000 |
---|---|---|
committer | uid32519 <none@none> | 2001-07-04 17:10:24 +0000 |
commit | 507e81ddf0454a0b740a69f69d917ce67075065f (patch) | |
tree | d935d772f266ee49a6a73341e1a34afda4b383d8 | |
parent | c8d64e87f29e42dc2f6f0068e575dd10188999af (diff) | |
download | xine-lib-507e81ddf0454a0b740a69f69d917ce67075065f.tar.gz xine-lib-507e81ddf0454a0b740a69f69d917ce67075065f.tar.bz2 |
spu support updated (unfinished) from James
CVS patchset: 250
CVS date: 2001/07/04 17:10:24
26 files changed, 1562 insertions, 152 deletions
diff --git a/include/xine.h.tmpl.in b/include/xine.h.tmpl.in index de7f78517..242994d28 100644 --- a/include/xine.h.tmpl.in +++ b/include/xine.h.tmpl.in @@ -29,7 +29,7 @@ \endverbatim */ /* - * $Id: xine.h.tmpl.in,v 1.24 2001/06/24 05:30:03 guenter Exp $ + * $Id: xine.h.tmpl.in,v 1.25 2001/07/04 17:10:24 uid32519 Exp $ * */ @@ -128,6 +128,7 @@ struct config_values_s { typedef struct vo_driver_s vo_driver_t; typedef void vo_frame_t; +typedef void vo_overlay_t; struct vo_driver_s { @@ -151,6 +152,9 @@ struct vo_driver_s { /* display a given frame */ void (*display_frame) (vo_driver_t *this, vo_frame_t *vo_img); + /* overlay functions */ + void (*set_overlay) (vo_driver_t *this, vo_overlay_t *overlay); + /* * these can be used by the gui directly: */ diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 2061d8843..bc17bb9bc 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg.c,v 1.23 2001/07/03 21:25:03 guenter Exp $ + * $Id: demux_mpeg.c,v 1.24 2001/07/04 17:10:24 uid32519 Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -536,6 +536,7 @@ static void *demux_mpeg_loop (void *this_gen) { this->audio_fifo->put (this->audio_fifo, buf); } } + xprintf (VERBOSE|DEMUX, "demux loop finished (status: %d, buf:%x)\n", this->status, w); printf ("demux loop finished (status: %d, buf:%x)\n", diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index be362d0f0..2aa9e2a48 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg_block.c,v 1.23 2001/07/03 21:25:04 guenter Exp $ + * $Id: demux_mpeg_block.c,v 1.24 2001/07/04 17:10:24 uid32519 Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -371,6 +371,11 @@ static void *demux_mpeg_block_loop (void *this_gen) { buf->decoder_info[0] = 0; /* stream finished */ this->audio_fifo->put (this->audio_fifo, buf); } + + buf = this->spu_fifo->buffer_pool_alloc (this->spu_fifo); + buf->type = BUF_CONTROL_END; + buf->decoder_info[0] = 0; /* stream finished */ + this->spu_fifo->put (this->spu_fifo, buf); } pthread_exit(NULL); @@ -411,6 +416,12 @@ static void demux_mpeg_block_stop (demux_plugin_t *this_gen) { this->audio_fifo->put (this->audio_fifo, buf); } + buf = this->spu_fifo->buffer_pool_alloc (this->spu_fifo); + buf->type = BUF_CONTROL_END; + buf->decoder_info[0] = 1; /* forced */ + + this->spu_fifo->put (this->spu_fifo, buf); + } static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) { @@ -454,6 +465,10 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen, this->audio_fifo->put (this->audio_fifo, buf); } + buf = this->spu_fifo->buffer_pool_alloc (this->spu_fifo); + buf->type = BUF_CONTROL_START; + this->spu_fifo->put (this->spu_fifo, buf); + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { int num_buffers = NUM_PREVIEW_BUFFERS; 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; +} + diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index b946f20e9..5070d63b9 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -25,7 +25,7 @@ endif # lib_LTLIBRARIES = $(xv_module) $(syncfb_module) $(xshm_module) $(aa_module) -xineplug_vo_out_xv_la_SOURCES = video_out_xv.c +xineplug_vo_out_xv_la_SOURCES = alphablend.c video_out_xv.c xineplug_vo_out_xv_la_LIBADD = $(XV_LIB) $(X_LIBS) -lXext xineplug_vo_out_xv_la_LDFLAGS = -avoid-version -module diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c new file mode 100644 index 000000000..ac77fbbce --- /dev/null +++ b/src/video_out/alphablend.c @@ -0,0 +1,350 @@ +//TOAST_SPU will define ALL spu entries - no matter the tranparency +//#define TOAST_SPU +/* #define PRIV_CLUT */ + +/* + * + * Copyright (C) 2000 Thomas Mirlacher + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * The author may be reached as <dent@linuxvideo.org> + * + *------------------------------------------------------------ + * + */ + +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "video_out.h" + +#define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) + +static inline uint16_t blendpixel_rgb16 (uint16_t dst, uint16_t src, + uint8_t o) +{ + return BLEND_COLOR (dst, src, 0xf800, o) | + BLEND_COLOR (dst, src, 0x07e0, o) | + BLEND_COLOR (dst, src, 0x001f, o); +} + +static inline uint32_t blendpixel_rgb24 (uint32_t dst, uint32_t src, + uint8_t o) +{ + return BLEND_COLOR (dst, src, 0xff0000, o) | + BLEND_COLOR (dst, src, 0x00ff00, o) | + BLEND_COLOR (dst, src, 0x0000ff, o); +} + +static inline uint32_t blendpixel_rgb32 (uint32_t dst, uint32_t src, + uint8_t o) +{ + return BLEND_COLOR (dst, src, 0xff0000, o) | + BLEND_COLOR (dst, src, 0x00ff00, o) | + BLEND_COLOR (dst, src, 0x0000ff, o); +} +/* +void blend_tux_rgb16 (uint8_t * img, int dst_width, int dst_height) +{ + int src_width = bg_width; + int src_height = bg_height; + uint8_t *src = (uint8_t *) bg_img_data; + static int x_off; + static int y_off; + static int x_dir = 1; + static int y_dir = 1; + static int o = 5; + static int o_dir = 1; + +// align right bottom + x_off += x_dir; + if (x_off > (dst_width - src_width)) + x_dir = -x_dir; + if (x_off <= 0) + x_dir = -x_dir; + + y_off += y_dir; + if (y_off > (dst_height - src_height)) + y_dir = -y_dir; + if (y_off <= 0) + y_dir = -y_dir; + +// cycle parameters + o += o_dir; + if (o >= 0xf) + o_dir = -o_dir; + if (o <= 1) + o_dir = -o_dir; +// + { + uint16_t *dst = (uint16_t *) img; + int x, + y; + + dst += y_off * dst_width; + for (y = 0; y < src_height; y++) { + dst += x_off; + for (x = 0; x < src_width; x++) { + if ((*src) - bg_start_index) + *dst = blendpixel_rgb16 (bg_palette_to_rgb [(*src) - bg_start_index], *dst, o); + src++; + dst++; + } + dst += dst_width - x - x_off; + } + } +} +*/ +// convenience + +#define uint24_t uint32_t + +#define BLEND(bpp, img, img_overl, dst_width, dst_height)\ +{ \ + static int o=5; \ + uint8_t *src = (uint8_t *) img_overl->data; \ + uint##bpp##_t *dst = (uint##bpp##_t *) img; \ + int x, y; \ + \ + dst += img_overl->y*dst_width; \ + for (y=0; y<img_overl->height; y++) { \ + dst += img_overl->x; \ + for (x=0; x<img_overl->width; x++) { \ + o = img_overl->trans[*src&0x0f]; \ + \ +/* if ((*src&0x0f) != 0) if alpha is != 0 */ \ + if (o) /* if alpha is != 0 */ \ + *dst = blendpixel_rgb##bpp (*dst, img_overl->clut[(*src&0x0f)]/*.y*/, o); \ +/* *dst = blendpixel_rgb##bpp (*dst, myclut[img_overl->clut[(*src&0x0f)]], o);*/\ + src++; \ + dst++; \ + } \ + dst += dst_width - x - img_overl->x; \ + } \ +} + +//void blend_rgb16 (uint8_t *img, overlay_buf_t *img_overl, int dst_width, int dst_height) +void blend_rgb (uint8_t * img, vo_overlay_t * img_overl, int dst_width, + int dst_height) +{ +#ifdef PRIV_CLUT + u_int myclut[] = { + 0x0000, + 0x20e2, + 0x83ac, + 0x4227, + 0xa381, + 0xad13, + 0xbdf8, + 0xd657, + 0xee67, + 0x6a40, + 0xd4c1, + 0xf602, + 0xf664, + 0xe561, + 0xad13, + 0xffdf, + }; +#endif + + BLEND (16, img, img_overl, dst_width, dst_height); + //blend_tux_rgb16 (img, dst_width, dst_height); +} + +void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, int dst_width, + int dst_height) +{ +//FIXME CLUT +#ifdef PRIV_CLUT + u_int myclut[] = { + 0x0000, + 0x20e2, + 0x83ac, + 0x4227, + 0xa381, + 0xad13, + 0xbdf8, + 0xd657, + 0xee67, + 0x6a40, + 0xd4c1, + 0xf602, + 0xf664, + 0xe561, + 0xad13, + 0xffdf, + }; +#endif + BLEND (24, img, img_overl, dst_width, dst_height); +} + +void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, int dst_width, + int dst_height) +{ +//FIXME CLUT +#ifdef PRIV_CLUT + u_int myclut[] = { + 0x0000, + 0x20e2, + 0x83ac, + 0x4227, + 0xa381, + 0xad13, + 0xbdf8, + 0xd657, + 0xee67, + 0x6a40, + 0xd4c1, + 0xf602, + 0xf664, + 0xe561, + 0xad13, + 0xffdf, + }; +#endif + BLEND (32, img, img_overl, dst_width, dst_height); +} + +#define BLEND_YUV(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) + +void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, + int dst_width, int dst_height) +{ +#ifdef PRIV_CLUT + clut_t my_clut[] = { + {y: 0x51, cr: 0xef, cb:0x5a}, + {y: 0xbf, cr: 0x80, cb:0x80}, + {y: 0x10, cr: 0x80, cb:0x80}, + {y: 0x28, cr: 0x6d, cb:0xef}, + {y: 0x51, cr: 0xef, cb:0x5a}, + {y: 0xbf, cr: 0x80, cb:0x80}, + {y: 0x36, cr: 0x80, cb:0x80}, + {y: 0x28, cr: 0x6d, cb:0xef}, + {y: 0x5c, cr: 0x80, cb:0x80}, + {y: 0xbf, cr: 0x80, cb:0x80}, + {y: 0x10, cr: 0x80, cb:0x80}, + {y: 0x28, cr: 0x6d, cb:0xef}, + {y: 0x5c, cr: 0x80, cb:0x80}, + {y: 0xbf, cr: 0x80, cb:0x80}, + {y: 0x1c, cr: 0x80, cb:0x80}, + {y: 0x28, cr: 0x6d, cb:0xef} + }; +#endif + + int src_width = img_overl->width; + int src_height = img_overl->height; + uint8_t *src_data = img_overl->data; + + int x_off = img_overl->x; + int y_off = img_overl->y; + + uint8_t *dst_y = dst_img + dst_width * y_off + x_off; + uint8_t *dst_cr = dst_img + dst_width * dst_height + + (y_off / 2) * (dst_width / 2) + (x_off / 2); + uint8_t *dst_cb = dst_img + (dst_width * dst_height * 5) / 4 + + (y_off / 2) * (dst_width / 2) + (x_off / 2); + + int x, + y; + + for (y = 0; y < src_height; y++) { + for (x = 0; x < src_width; x++) { + uint8_t clr; + uint8_t o; + + clr = img_overl->clut[*src_data & 0x0f]; + o = img_overl->trans[*src_data & 0x0f]; + + if (clr) +// *INDENT-OFF* +#ifdef PRIV_CLUT + *dst_y = BLEND_YUV (*dst_y, my_clut[clr].y, o); +#else + *dst_y = BLEND_YUV (*dst_y, img_overl->clut[clr]/*.y*/, o); +#endif +// *INDENT-ON* + dst_y++; + + if (y & x & 1) { + if (clr) { +// *INDENT-OFF* +#ifdef PRIV_CLUT + *dst_cr = BLEND_YUV (*dst_cr, my_clut[clr].cr, o); + *dst_cb = BLEND_YUV (*dst_cb, my_clut[clr].cb, o); +#else + *dst_cr = BLEND_YUV (*dst_cr, img_overl->clut [clr]/*.cr*/, o); + *dst_cb = BLEND_YUV (*dst_cb, img_overl->clut [clr]/*.cb*/, o); +#endif +// *INDENT-ON* + } + dst_cr++; + dst_cb++; + } + src_data++; + } + + dst_y += dst_width - src_width; + + if (y & 1) { + dst_cr += (dst_width - src_width) / 2; + dst_cb += (dst_width - src_width) / 2; + } + } +} + +inline int is_blank (uint8_t * ptr, int width) +{ + int x; + + for (x = 0; x < width; x++) { + if ((*ptr & 0x0f) && (*ptr >> 4)) + return 0; // color != 0 && alpha != 0 + ptr++; + } + + return 1; // blank line +} + +void crop_overlay (vo_overlay_t * overlay) +{ + uint8_t *data = overlay->data; + int height = overlay->height; + int width = overlay->width; + int y; + + /* + * Shrink from bottom + */ + + for (y=height - 1;y >= 0 && is_blank (&data[y * width], width); y--); + height = y + 1; + + /* + * Shrink from top + */ + for (y=0; y < height && is_blank (&data[y * width], width); y++); + height -= y; + + /* + * Shift data + */ + overlay->y -= y; + overlay->height = height; + + memcpy (data, &data[y * width], height * width); +} diff --git a/src/video_out/alphablend.h b/src/video_out/alphablend.h new file mode 100644 index 000000000..7afa470f7 --- /dev/null +++ b/src/video_out/alphablend.h @@ -0,0 +1,39 @@ + +/* + * + * Copyright (C) 2000 Thomas Mirlacher + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * The author may be reached as <dent@linuxvideo.org> + * + *------------------------------------------------------------ + * + */ + +#ifndef __ALPHABLEND_H__ +#define __ALPHABLEND_H__ + +#include "video_out.h" + +void blend_rgb (uint8_t * img, vo_overlay_t * overlay, int width, + + int height); +void blend_yuv (uint8_t * img, vo_overlay_t * overlay, int width, + + int height); +void crop_overlay (vo_overlay_t * overlay); + +#endif diff --git a/src/video_out/video_out_aa.c b/src/video_out/video_out_aa.c index 179157e7c..1ab490ee2 100644 --- a/src/video_out/video_out_aa.c +++ b/src/video_out/video_out_aa.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_aa.c,v 1.7 2001/06/14 18:32:57 guenter Exp $ + * $Id: video_out_aa.c,v 1.8 2001/07/04 17:10:24 uid32519 Exp $ * * video_out_aa.c, ascii-art output plugin for xine * @@ -261,6 +261,9 @@ static void aa_get_property_min_max (vo_driver_t *this_gen, *max = 0; } +static void aa_set_overlay (vo_driver_t *this, vo_overlay_t *overlay) { +} + static void aa_exit (vo_driver_t *this_gen) { } @@ -283,12 +286,13 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->vo_driver.get_property_min_max = aa_get_property_min_max; this->vo_driver.gui_data_exchange = NULL; this->vo_driver.exit = aa_exit; + this->vo_driver.set_overlay = aa_set_overlay; return (vo_driver_t*) this; } static vo_info_t vo_info_aa = { - VIDEO_OUT_IFACE_VERSION, + 2, "aa", "xine video output plugin using the ascii-art library", VISUAL_TYPE_AA, diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index a7ec000a1..f3a4d52c8 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_syncfb.c,v 1.7 2001/07/04 14:01:50 uid56437 Exp $ + * $Id: video_out_syncfb.c,v 1.8 2001/07/04 17:10:24 uid32519 Exp $ * * video_out_syncfb.c, Matrox G400 video extension interface for xine * @@ -866,7 +866,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual) { static vo_info_t vo_info_mga = { - VIDEO_OUT_IFACE_VERSION, + 1, "Syncfb", "xine video output plugin using MGA Teletux (syncfb) video extension", VISUAL_TYPE_X11, diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index b4f9d5e65..63168b852 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xshm.c,v 1.13 2001/07/04 14:01:50 uid56437 Exp $ + * $Id: video_out_xshm.c,v 1.14 2001/07/04 17:10:24 uid32519 Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -94,6 +94,7 @@ typedef struct xshm_driver_s { yuv2rgb_t *yuv2rgb; xshm_frame_t *cur_frame; + vo_overlay_t *overlay; /* size / aspect ratio calculations */ int delivered_width; /* everything is set up for these frame dimensions */ @@ -652,6 +653,13 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { } } +/* Stores an overlay in the Video Out driver */ +static void xshm_set_overlay (vo_driver_t *this_gen, vo_overlay_t *overlay) { + xshm_driver_t *this = (xshm_driver_t *) this_gen; + + this->overlay = overlay; +} + static int xshm_get_property (vo_driver_t *this_gen, int property) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -823,12 +831,14 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->vo_driver.alloc_frame = xshm_alloc_frame; this->vo_driver.update_frame_format = xshm_update_frame_format; this->vo_driver.display_frame = xshm_display_frame; + this->vo_driver.set_overlay = xshm_set_overlay; this->vo_driver.get_property = xshm_get_property; this->vo_driver.set_property = xshm_set_property; this->vo_driver.get_property_min_max = xshm_get_property_min_max; this->vo_driver.gui_data_exchange = xshm_gui_data_exchange; this->vo_driver.exit = xshm_exit; + /* * * depth in X11 terminology land is the number of bits used to @@ -924,7 +934,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { } static vo_info_t vo_info_shm = { - VIDEO_OUT_IFACE_VERSION, + 2, "XShm", "xine video output plugin using the MIT X shared memory extension", VISUAL_TYPE_X11, diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 741bfdd20..ed49b6324 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xv.c,v 1.47 2001/06/25 09:51:47 guenter Exp $ + * $Id: video_out_xv.c,v 1.48 2001/07/04 17:10:24 uid32519 Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -54,6 +54,8 @@ #include "video_out.h" #include "video_out_x11.h" #include "xine_internal.h" +/* #include "overlay.h" */ +#include "alphablend.h" uint32_t xine_debug; @@ -102,6 +104,7 @@ typedef struct { uint32_t capabilities; xv_frame_t *cur_frame; + vo_overlay_t *overlay; /* size / aspect ratio calculations */ int delivered_width; /* everything is set up for @@ -135,8 +138,6 @@ static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; - printf ("video_out_xv: get capabilities\n"); - return this->capabilities; } @@ -396,9 +397,6 @@ static void xv_update_frame_format (vo_driver_t *this_gen, frame->ratio_code = ratio_code; } -/* - * - */ static void xv_adapt_to_output_area (xv_driver_t *this, int dest_x, int dest_y, int dest_width, int dest_height) { @@ -447,9 +445,6 @@ static void xv_adapt_to_output_area (xv_driver_t *this, XUnlockDisplay (this->display); } -/* - * - */ static void xv_calc_format (xv_driver_t *this, int width, int height, int ratio_code) { @@ -567,6 +562,10 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xv_calc_format (this, frame->width, frame->height, frame->ratio_code); } +// Alpha Blend here + if (this->overlay) { + blend_yuv( frame->image->data, this->overlay, frame->width, frame->height); + } XLockDisplay (this->display); @@ -595,9 +594,13 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { } } -/* - * - */ +/* Stores an overlay in the Video Out driver */ +static void xv_set_overlay (vo_driver_t *this_gen, vo_overlay_t *overlay) { + xv_driver_t *this = (xv_driver_t *) this_gen; + + this->overlay = overlay; +} + static int xv_get_property (vo_driver_t *this_gen, int property) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -605,9 +608,6 @@ static int xv_get_property (vo_driver_t *this_gen, int property) { return this->props[property].value; } -/* - * - */ static int xv_set_property (vo_driver_t *this_gen, int property, int value) { @@ -649,9 +649,6 @@ static int xv_set_property (vo_driver_t *this_gen, return value; } -/* - * - */ static void xv_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { @@ -661,9 +658,6 @@ static void xv_get_property_min_max (vo_driver_t *this_gen, *max = this->props[property].max; } -/* - * - */ static int xv_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { @@ -730,9 +724,6 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, return 0; } -/* - * - */ static void xv_exit (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -744,9 +735,6 @@ static void xv_exit (vo_driver_t *this_gen) { XUnlockDisplay (this->display); } -/* - * - */ static int xv_check_yv12 (Display *display, XvPortID port) { XvImageFormatValues * formatValues; int formats; @@ -763,9 +751,6 @@ static int xv_check_yv12 (Display *display, XvPortID port) { return 1; } -/* - * - */ static void xv_check_capability (xv_driver_t *this, uint32_t capability, int property, XvAttribute attr, @@ -786,9 +771,6 @@ static void xv_check_capability (xv_driver_t *this, this->config->lookup_int (this->config, str_prop, nDefault)); } -/* - * - */ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { xv_driver_t *this; @@ -875,6 +857,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->config = config; this->display = visual->display; + this->overlay = NULL; this->screen = visual->screen; this->display_ratio = visual->display_ratio; this->request_dest_size = visual->request_dest_size; @@ -897,6 +880,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->vo_driver.alloc_frame = xv_alloc_frame; this->vo_driver.update_frame_format = xv_update_frame_format; this->vo_driver.display_frame = xv_display_frame; + this->vo_driver.set_overlay = xv_set_overlay; this->vo_driver.get_property = xv_get_property; this->vo_driver.set_property = xv_set_property; this->vo_driver.get_property_min_max = xv_get_property_min_max; @@ -1010,11 +994,8 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { return &this->vo_driver; } -/* - * - */ static vo_info_t vo_info_xv = { - VIDEO_OUT_IFACE_VERSION, + 2, "Xv", "xine video output plugin using the MIT X video extension", VISUAL_TYPE_X11, diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 17558fdd2..4726c331d 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -8,14 +8,14 @@ EXTRA_DIST = cpu_accel.c lib_LTLIBRARIES = libxine.la -libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c monitor.c \ - utils.c load_plugins.c video_decoder.c spu_decoder.c \ +libxine_la_SOURCES = xine.c metronom.c configfile.c spu_decoder.c buffer.c monitor.c \ + utils.c load_plugins.c video_decoder.c \ audio_decoder.c video_out.c libxine_la_LIBADD = cpu_accel.lo \ - $(top_srcdir)/src/libspudec/libspudec.la \ $(THREAD_LIBS) \ - $(DYNAMIC_LD_LIBS) + $(DYNAMIC_LD_LIBS) \ -lm + libxine_la_LDFLAGS = -version-info 5:0:5 include_HEADERS = buffer.h metronom.h configfile.h \ diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 1a7d97424..a7b1aa924 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: load_plugins.c,v 1.27 2001/07/01 23:37:05 guenter Exp $ + * $Id: load_plugins.c,v 1.28 2001/07/04 17:10:24 uid32519 Exp $ * * * Load input/demux/audio_out/video_out/codec plugins @@ -268,6 +268,9 @@ void load_decoder_plugins (xine_t *this, /* * clean up first */ + this->cur_spu_decoder_plugin = NULL; + for (i=0; i<DECODER_PLUGIN_MAX; i++) + this->spu_decoder_plugins[i] = NULL; this->cur_video_decoder_plugin = NULL; for (i=0; i<DECODER_PLUGIN_MAX; i++) @@ -312,6 +315,29 @@ void load_decoder_plugins (xine_t *this, } else { void *(*initplug) (int, config_values_t *); + + /* + * does this plugin provide an spu decoder plugin? + */ + + if((initplug = dlsym(plugin, "init_spu_decoder_plugin")) != NULL) { + + spu_decoder_t *sdp; + int streamtype; + + sdp = (spu_decoder_t *) initplug(iface_version, config); + printf("SPU Can Handle ?\n"); + for (streamtype = 0; streamtype<256; streamtype++) { + if (sdp->can_handle (sdp, (streamtype<<16) | BUF_SPU_BASE)) + printf("SPU Can Handle yes %x\n",streamtype); + this->spu_decoder_plugins[streamtype] = sdp; + } + + printf("spu decoder plugin found : %s\n", + sdp->get_identifier()); + } + + /* * does this plugin provide an video decoder plugin? @@ -360,6 +386,7 @@ void load_decoder_plugins (xine_t *this, } } + this->cur_spu_decoder_plugin = NULL; this->cur_video_decoder_plugin = NULL; this->cur_audio_decoder_plugin = NULL; } @@ -498,22 +525,30 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config, if ((getinfo = dlsym(plugin, "get_video_out_plugin_info")) != NULL) { vo_info = getinfo(); - - if (!strcmp(id, vo_info->id)) { - void *(*initplug) (config_values_t *, void *); + + if (!strcmp(id, vo_info->id) ) { + + if (vo_info->interface_version == VIDEO_OUT_IFACE_VERSION) { + + void *(*initplug) (config_values_t *, void *); - if((initplug = dlsym(plugin, "init_video_out_plugin")) != NULL) { - - vod = (vo_driver_t *) initplug(config, visual); - - if (vod) - printf("load_plugins: video output plugin %s successfully" - " loaded.\n", id); - else - printf("load_plugins: video output plugin %s: " - "init_video_out_plugin failed.\n", str); + if((initplug = dlsym(plugin, "init_video_out_plugin")) != NULL) { + + vod = (vo_driver_t *) initplug(config, visual); + + if (vod) + printf("load_plugins: video output plugin %s successfully" + " loaded.\n", id); + else + printf("load_plugins: video output plugin %s: " + "init_video_out_plugin failed.\n", str); + + return vod; + } + } else { - return vod; + printf("load_plugins: video output plugin %s: " + "wrong interface version %d.\n", str, vo_info->interface_version); } } } diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index de24dad76..ef6706ebf 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: metronom.c,v 1.13 2001/07/03 21:25:04 guenter Exp $ + * $Id: metronom.c,v 1.14 2001/07/04 17:10:24 uid32519 Exp $ */ #ifdef HAVE_CONFIG_H @@ -390,7 +390,6 @@ static uint32_t metronom_got_audio_samples (metronom_t *this, uint32_t pts, uint pthread_mutex_lock (&this->lock); if (pts) { - int32_t diff; /* * first audio pts ? diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 6422d4f62..e7080b57d 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: metronom.h,v 1.5 2001/06/24 02:19:29 guenter Exp $ + * $Id: metronom.h,v 1.6 2001/07/04 17:10:24 uid32519 Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -125,7 +125,7 @@ struct metronom_s { /* * start metronom clock (no clock reset) */ - void (*start_clock) (metronom_t *this, int32_t pts); + void (*start_clock) (metronom_t *this, uint32_t pts); /* diff --git a/src/xine-engine/monitor.h b/src/xine-engine/monitor.h index e338be535..f4033a1d5 100644 --- a/src/xine-engine/monitor.h +++ b/src/xine-engine/monitor.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: monitor.h,v 1.1 2001/04/18 22:36:07 f1rmb Exp $ + * $Id: monitor.h,v 1.2 2001/07/04 17:10:24 uid32519 Exp $ * * debug print and profiling functions * @@ -30,18 +30,18 @@ extern uint32_t xine_debug; -#define VERBOSE (xine_debug & 0x8000>>1) -#define METRONOM (xine_debug & 0x8000>>2) -#define AUDIO (xine_debug & 0x8000>>3) -#define DEMUX (xine_debug & 0x8000>>4) -#define INPUT (xine_debug & 0x8000>>5) -#define VIDEO (xine_debug & 0x8000>>6) -#define VPTS (xine_debug & 0x8000>>7) -#define MPEG (xine_debug & 0x8000>>8) -#define VAVI (xine_debug & 0x8000>>9) -#define AC3 (xine_debug & 0x8000>>10) -#define LOOP (xine_debug & 0x8000>>11) -#define GUI (xine_debug & 0x8000>>12) +#define VERBOSE (xine_debug & 0x8000>>1) // 16384 +#define METRONOM (xine_debug & 0x8000>>2) // 8192 +#define AUDIO (xine_debug & 0x8000>>3) // 4096 +#define DEMUX (xine_debug & 0x8000>>4) // 2048 +#define INPUT (xine_debug & 0x8000>>5) // 1024 +#define VIDEO (xine_debug & 0x8000>>6) // 512 +#define VPTS (xine_debug & 0x8000>>7) // 256 +#define MPEG (xine_debug & 0x8000>>8) // 128 +#define VAVI (xine_debug & 0x8000>>9) // 64 +#define AC3 (xine_debug & 0x8000>>10) // 32 +#define LOOP (xine_debug & 0x8000>>11) // 16 +#define GUI (xine_debug & 0x8000>>12) // 8 #define perr(FMT,ARGS...) {fprintf(stderr, FMT, ##ARGS);fflush(stderr);} diff --git a/src/xine-engine/spu_decoder.c b/src/xine-engine/spu_decoder.c index 03f008367..0878bf06a 100644 --- a/src/xine-engine/spu_decoder.c +++ b/src/xine-engine/spu_decoder.c @@ -17,8 +17,10 @@ * 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_decoder.c,v 1.2 2001/06/18 15:43:01 richwareham Exp $ + * $Id: spu_decoder.c,v 1.3 2001/07/04 17:10:24 uid32519 Exp $ * + + * functions that implement spu decoding */ #ifdef HAVE_CONFIG_H @@ -27,52 +29,95 @@ #include "xine_internal.h" -#include "libspudec/spudec.h" - void *spu_decoder_loop (void *this_gen) { buf_element_t *buf; xine_t *this = (xine_t *) this_gen; int running = 1; - int streamtype; - spudec_t *decoder; + int i; + spu_decoder_t *decoder; - decoder = this->spu_decoder; while (running) { - /* printf ("video_decoder: getting buffer...\n"); */ - buf = this->spu_fifo->get (this->spu_fifo); - if (buf->input_pos) - this->cur_input_pos = buf->input_pos; - /* printf ("spu_decoder: got buffer %d\n", buf->type); */ + this->cur_input_pos = buf->input_pos; switch (buf->type) { + case BUF_CONTROL_START: + if (this->cur_spu_decoder_plugin) { + this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); + this->cur_spu_decoder_plugin = NULL; + } + + pthread_mutex_lock (&this->xine_lock); + this->spu_finished = 0; + pthread_mutex_unlock (&this->xine_lock); + + for (i=0 ; i<50; i++) + this->spu_track_map[0] = 0; + + this->spu_track_map_entries = 0; + break; case BUF_CONTROL_END: + if (this->cur_spu_decoder_plugin) { + this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); + this->cur_spu_decoder_plugin = NULL; + } + + pthread_mutex_lock (&this->xine_lock); + + this->spu_finished = 1; + + if (this->video_finished) { + pthread_mutex_unlock (&this->xine_lock); + xine_notify_stream_finished (this); + } else + pthread_mutex_unlock (&this->xine_lock); + break; case BUF_CONTROL_QUIT: + if (this->cur_spu_decoder_plugin) { + this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); + this->cur_spu_decoder_plugin = NULL; + } running = 0; break; default: if ( (buf->type & 0xFF000000) == BUF_SPU_BASE ) { - int stream_id; - - printf ("spu_decoder: got an SPU buffer, type %08x\n", buf->type); - - stream_id = buf->type & 0xFF; - if(decoder) { - decoder->push_packet(decoder, buf); + + /* now, decode this buffer if it's the right track */ + + if ( (buf->type & 0xFFFF)== this->spu_channel) { + + int streamtype = (buf->type>>16) & 0xFF; + decoder = this->spu_decoder_plugins [streamtype]; + printf("SPU DECODER: %p\n",decoder); + if (decoder) { + if (this->cur_spu_decoder_plugin != decoder) { + + if (this->cur_spu_decoder_plugin) + this->cur_spu_decoder_plugin->close (this->cur_spu_decoder_plugin); + + this->cur_spu_decoder_plugin = decoder; + + this->cur_spu_decoder_plugin->init (this->cur_spu_decoder_plugin, this->video_out); + } + + printf ("spu_decoder: decoder data sent\n"); + decoder->decode_data (decoder, buf); + } } - } + } else + fprintf (stderr,"spu_decoder: unknown buffer type: %08x\n", buf->type); } - + buf->free_buffer (buf); } @@ -80,15 +125,9 @@ void *spu_decoder_loop (void *this_gen) { } void spu_decoder_init (xine_t *this) { - buf_element_t *buf; - - this->spu_decoder = spudec_init(this); this->spu_fifo = fifo_buffer_new (1500, 4096); - - buf = this->spu_fifo->buffer_pool_alloc (this->spu_fifo); - buf->type = BUF_CONTROL_START; - this->spu_fifo->put (this->spu_fifo, buf); + printf ("spu_decoder_init: thread starting %p\n",this->video_out); pthread_create (&this->spu_thread, NULL, spu_decoder_loop, this) ; } @@ -98,15 +137,13 @@ void spu_decoder_shutdown (xine_t *this) { buf_element_t *buf; void *p; - this->spu_fifo->clear(this->spu_fifo); + /* this->spu_fifo->clear(this->spu_fifo); */ buf = this->spu_fifo->buffer_pool_alloc (this->spu_fifo); buf->type = BUF_CONTROL_QUIT; this->spu_fifo->put (this->spu_fifo, buf); - spudec_close(this->spu_decoder); - this->spu_decoder = NULL; - pthread_join (this->spu_thread, &p); } + diff --git a/src/xine-engine/spu_decoder.h b/src/xine-engine/spu_decoder.h new file mode 100644 index 000000000..7ece22335 --- /dev/null +++ b/src/xine-engine/spu_decoder.h @@ -0,0 +1,152 @@ +/* + * 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: spu_decoder.h,v 1.1 2001/07/04 17:10:24 uid32519 Exp $ + */ +#ifndef HAVE_SPU_OUT_H +#define HAVE_SPU_OUT_H + +#include <inttypes.h> + +#if defined(XINE_COMPILE) +#include "metronom.h" +#include "configfile.h" +#endif + + +#define SPU_OUT_IFACE_VERSION 1 + +/* + * spu_functions_s contains the functions every spu output + * driver plugin has to implement. + */ + +typedef struct spu_functions_s spu_functions_t; + +struct spu_functions_s { + + /* + * + * find out what output modes + capatilities are supported by + * this plugin (constants for the bit vector to return see above) + * + * See SPU_CAP_* bellow. + */ + uint32_t (*get_capabilities) (spu_functions_t *this); + + /* + * connect this driver to the xine engine + */ + void (*connect) (spu_functions_t *this, metronom_t *metronom); + + /* + * open the driver and make it ready to receive spu data + * buffers may be flushed(!) + * + * return value: <=0 : failure, 1 : ok + */ + + int (*open)(spu_functions_t *this, uint32_t bits, uint32_t rate, int mode); + + /* + * write spu data to output buffer - may block + * spu driver must sync sample playback with metronom + */ + + void (*write_spu_data)(spu_functions_t *this, + int16_t* spu_data, uint32_t num_samples, + uint32_t pts); + + /* + * this is called when the decoder no longer uses the spu + * output driver - the driver should get ready to get opened() again + */ + + void (*close)(spu_functions_t *this); + + /* + * shut down this spu output driver plugin and + * free all resources allocated + */ + + void (*exit) (spu_functions_t *this); + + /* + * Get, Set a property of spu driver. + * + * get_property() return 1 in success, 0 on failure. + * set_property() return value on success, ~value on failure. + * + * See AC_PROP_* bellow for available properties. + */ + int (*get_property) (spu_functions_t *this, int property); + + int (*set_property) (spu_functions_t *this, int property, int value); + +}; + + +/* + * to build a dynamic spu output plugin, + * you have to implement these functions: + * + * + * spu_functions_t *init_spu_out_plugin (config_values_t *config) + * + * init this plugin, check if device is available + * + * spu_info_t *get_spu_out_plugin_info () + * + * peek at some (static) information about the plugin without initializing it + * + */ + +/* + * spu output modes + capabilities + */ + +#define SPU_CAP_NOCAP 0x00000000 /* Driver have no capabilities */ +#define SPU_CAP_MODE_AC3 0x00000001 /* Driver support AC3 output */ +#define SPU_CAP_MODE_AC5 0x00000002 /* Driver support AC5 output */ +/* 1 sample == 2 bytes */ +#define SPU_CAP_MODE_MONO 0x00000004 /* Driver support mono output */ + /* 1 sample == 4 bytes */ +#define SPU_CAP_MODE_STEREO 0x00000008 /* Driver support stereo output */ + /* 1 sample == 8 bytes */ +#define SPU_CAP_MODE_4CHANNEL 0x00000010 /* Driver support 4 channels */ +/* 1 sample == 10 bytes */ +#define SPU_CAP_MODE_5CHANNEL 0x00000020 /* Driver support 5 channels */ +#define SPU_CAP_MIXER_VOL 0x00000040 /* Driver support mixer control */ +#define SPU_CAP_PCM_VOL 0x00000080 /* Driver support pcm control */ +#define SPU_CAP_MUTE_VOL 0x00000100 /* Driver can mute volume */ + +/* properties supported by get/set_property() */ +#define SPU_PROP_MIXER_VOL 0 +#define SPU_PROP_PCM_VOL 1 +#define SPU_PROP_MUTE_VOL 2 + +typedef struct spu_info_s { + + int interface_version; + char *id; + char *description; + int priority; +} spu_info_t ; + +#endif diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 3fb974022..b6a98e8d1 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 the xine project + * Copyright (C) 2000, 2001 the xine project * * This file is part of xine, a unix video player. * @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.27 2001/07/04 14:14:39 uid56437 Exp $ + * $Id: video_out.c,v 1.28 2001/07/04 17:10:24 uid32519 Exp $ * */ @@ -29,15 +29,13 @@ #include <sys/time.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> +#include <string.h> #include "video_out.h" #include "utils.h" #include "monitor.h" -#include "libspudec/spudec.h" - #define NUM_FRAME_BUFFERS 20 struct img_buf_fifo_s { @@ -148,7 +146,7 @@ static void *video_out_loop (void *this_gen) { /* int dummysignum; */ - struct timespec ts; + /* struct timespec ts; */ /* printf ("%d video_out start\n", getpid()); */ /* @@ -278,11 +276,6 @@ static void *video_out_loop (void *this_gen) { img->bDisplayLock = 0; pthread_mutex_unlock (&img->mutex); - /* Overlay SPU FIXME: Check image format */ - - this->spu_decoder->overlay_yuv (this->spu_decoder, pts, - img->base[0], img->base[1], img->base[2]); - xprintf (VERBOSE|VIDEO, "video_out : passing to video driver, image with pts = %d\n", pts); this->driver->display_frame (this->driver, img); } @@ -496,7 +489,18 @@ static int vo_frame_draw (vo_frame_t *img) { return frames_to_skip; } -vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom, spudec_t *spu_decoder) { +static vo_overlay_t *vo_get_overlay (vo_instance_t *this, + int width, int height) { + /* FIXME: implement */ + return NULL; +} + +static void vo_queue_overlay (vo_instance_t *this, vo_overlay_t *overlay) { + + /* FIXME: implement */ +} + +vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) { vo_instance_t *this; int i; @@ -505,13 +509,14 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom, spude this->driver = driver; this->metronom = metronom; - this->spu_decoder = spu_decoder; this->open = vo_open; this->get_frame = vo_get_frame; this->close = vo_close; this->exit = vo_exit; this->get_capabilities = vo_get_capabilities; + this->get_overlay = vo_get_overlay; + this->queue_overlay = vo_queue_overlay; this->num_frames_delivered = 0; this->num_frames_skipped = 0; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index becfba058..a4826c61f 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2000-2001 the xine project * - * This file is part of xine, a unix video player. + * 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 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.h,v 1.8 2001/06/18 15:43:01 richwareham Exp $ + * $Id: video_out.h,v 1.9 2001/07/04 17:10:24 uid32519 Exp $ * * * xine version of video_out.h @@ -48,8 +48,8 @@ typedef struct vo_frame_s vo_frame_t; typedef struct vo_driver_s vo_driver_t ; typedef struct vo_instance_s vo_instance_t; typedef struct img_buf_fifo_s img_buf_fifo_t; +typedef struct vo_overlay_s vo_overlay_t; -typedef struct spudec_s spudec_t; /* public part, video drivers may add private fields */ struct vo_frame_s { @@ -111,6 +111,10 @@ struct vo_instance_s { vo_frame_t* (*get_frame) (vo_instance_t *this, uint32_t width, uint32_t height, int ratio_code, int format, uint32_t duration); + + /* overlay stuff */ + vo_overlay_t* (*get_overlay) (vo_instance_t *this); + void (*queue_overlay) (vo_instance_t *this, vo_overlay_t *overlay); /* video driver is no longer used by decoder => close */ void (*close) (vo_instance_t *this); @@ -122,7 +126,6 @@ struct vo_instance_s { vo_driver_t *driver; metronom_t *metronom; - spudec_t *spu_decoder; img_buf_fifo_t *free_img_buf_queue; img_buf_fifo_t *display_img_buf_queue; @@ -188,7 +191,7 @@ struct vo_instance_s { * from generic vo functions. */ -#define VIDEO_OUT_IFACE_VERSION 1 +#define VIDEO_OUT_IFACE_VERSION 2 struct vo_driver_s { @@ -212,6 +215,10 @@ struct vo_driver_s { /* display a given frame */ void (*display_frame) (vo_driver_t *this, vo_frame_t *vo_img); + /* overlay functions */ + void (*set_overlay) (vo_driver_t *this, vo_overlay_t *overlay); + + /* * these can be used by the gui directly: */ @@ -236,13 +243,32 @@ struct vo_driver_s { }; +struct vo_overlay_s { + uint8_t *data; /* 7-4: mixer key, 3-0: color index */ + int x; /* x start of subpicture area */ + int y; /* y start of subpicture area */ + int width; /* width of subpicture area */ + int height; /* height of subpicture area */ + + uint8_t clut[4]; /* color lookup table */ + uint8_t trans[4]; /* mixer key table */ + + uint32_t PTS, duration; /* 1/90000 s */ + + struct overlay_s *next; /* optionally more overlays */ + + /* private stuff */ + int _x; /* current destination x, y */ + int _y; + int offset[2]; /* address in PXD to fetch next rle-code from, one per field */ +}; /* * build a video_out_instance from * a given video driver */ -vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom, spudec_t *spu_decoder) ; +vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) ; /* * to build a dynamic video output plugin diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 000401caa..c8fd4dc2a 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * 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.c,v 1.31 2001/07/03 21:25:04 guenter Exp $ + * $Id: xine.c,v 1.32 2001/07/04 17:10:24 uid32519 Exp $ * * top-level xine functions * @@ -49,7 +49,8 @@ #ifdef ARCH_X86 #include "libw32dll/w32codec.h" #endif -#include "libspudec/spudec.h" +#include "libspudec/spu_decoder_api.h" +#include "spu_decoder.h" #include "input/input_plugin.h" #include "metronom.h" #include "configfile.h" @@ -95,8 +96,6 @@ void xine_stop (xine_t *this) { this->cur_input_plugin = NULL; } - this->spu_fifo->clear(this->spu_fifo); - printf ("xine_stop: done\n"); pthread_mutex_unlock (&this->xine_lock); @@ -364,6 +363,7 @@ xine_t *xine_init (vo_driver_t *vo, gui_branched_cb_t branched_cb) { xine_t *this = xmalloc (sizeof (xine_t)); + printf("xine_init entered\n"); this->stream_end_cb = stream_end_cb; this->get_next_mrl_cb = get_next_mrl_cb; @@ -398,26 +398,25 @@ xine_t *xine_init (vo_driver_t *vo, this->cur_input_pos = 0; /* - * init SPU decoder (must be done before video decoder - * so that this->spu_decoder is valid). - */ - spu_decoder_init (this); - - /* * init and start decoder threads */ load_decoder_plugins (this, config, DECODER_PLUGIN_IFACE_VERSION); - this->video_out = vo_new_instance (vo, this->metronom, this->spu_decoder); + this->video_out = vo_new_instance (vo, this->metronom); video_decoder_init (this); + /* + * init SPU decoder (must be done before video decoder + * so that this->spu_decoder is valid). + */ + spu_decoder_init (this); if(ao) { this->audio_out = ao; this->audio_out->connect (this->audio_out, this->metronom); } audio_decoder_init (this); - + printf("xine_init returning\n"); return this; } diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 9712196cf..2269c2117 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -17,7 +17,7 @@ * 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_internal.h,v 1.26 2001/06/23 14:05:47 f1rmb Exp $ + * $Id: xine_internal.h,v 1.27 2001/07/04 17:10:24 uid32519 Exp $ * */ @@ -30,6 +30,8 @@ #include "video_out.h" #include "audio_out.h" #include "metronom.h" +#include "spu_decoder.h" +#include "libspudec/spu_decoder_api.h" #define INPUT_PLUGIN_MAX 50 #define DEMUXER_PLUGIN_MAX 50 @@ -128,9 +130,15 @@ typedef struct xine_s { off_t cur_input_pos; char cur_mrl[1024]; + spu_functions_t *spu_out; fifo_buffer_t *spu_fifo; pthread_t spu_thread; - spudec_t *spu_decoder; + spu_decoder_t *spu_decoder_plugins[DECODER_PLUGIN_MAX]; + int num_spu_decoder_plugins; + spu_decoder_t *cur_spu_decoder_plugin; + uint32_t spu_track_map[50]; + int spu_track_map_entries; + int spu_finished; int audio_channel; int spu_channel; |