summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEduard Hasenleithner <ehasenle@users.sourceforge.net>2001-08-13 12:52:33 +0000
committerEduard Hasenleithner <ehasenle@users.sourceforge.net>2001-08-13 12:52:33 +0000
commitda711d47f121b937d2ec4a15a7e607af9f528ce5 (patch)
tree5857b0175ab090206ca629bd34a8be6d4f6a50fc /src
parent9c7fc92c6c391b037393721dbe8742ddd260b1d1 (diff)
downloadxine-lib-da711d47f121b937d2ec4a15a7e607af9f528ce5.tar.gz
xine-lib-da711d47f121b937d2ec4a15a7e607af9f528ce5.tar.bz2
major rewrite of the subpicture mechanism in order to support menus.
CVS patchset: 416 CVS date: 2001/08/13 12:52:33
Diffstat (limited to 'src')
-rw-r--r--src/libspudec/Makefile.am3
-rw-r--r--src/libspudec/spu.c485
-rw-r--r--src/libspudec/spu.h41
-rw-r--r--src/libspudec/spu_decoder_api.h18
-rw-r--r--src/libspudec/xine_decoder.c259
-rw-r--r--src/video_out/alphablend.c47
-rw-r--r--src/xine-engine/events.h10
-rw-r--r--src/xine-engine/load_plugins.c4
-rw-r--r--src/xine-engine/video_out.c137
-rw-r--r--src/xine-engine/video_out.h42
-rw-r--r--src/xine-engine/xine.c30
-rw-r--r--src/xine-engine/xine_internal.h4
12 files changed, 543 insertions, 537 deletions
diff --git a/src/libspudec/Makefile.am b/src/libspudec/Makefile.am
index 578f038d4..9e5d8ca4b 100644
--- a/src/libspudec/Makefile.am
+++ b/src/libspudec/Makefile.am
@@ -9,7 +9,8 @@ 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
+noinst_HEADERS = spu.h
+include_HEADERS = spu_decoder_api.h
##
## Install header files (default=$includedir/xine)
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c
index f28e74884..8c572bf54 100644
--- a/src/libspudec/spu.c
+++ b/src/libspudec/spu.c
@@ -65,26 +65,8 @@
#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
@@ -93,8 +75,168 @@ struct reassembly_s {
#define LOG(lvl, fmt...)
#endif
+void spuInit (void)
+{
+}
+
+/* Return value: reassembly complete = 1 */
+int spuReassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len)
+{
+ LOG (LOG_DEBUG, "pkt_len: %d", pkt_len);
+
+ if (start) {
+ seq->seq_len = (((u_int)pkt_data[0])<<8) | pkt_data[1];
+ seq->cmd_offs = (((u_int)pkt_data[2])<<8) | pkt_data[3];
+
+ if (seq->buf_len < seq->seq_len) {
+ if (seq->buf)
+ free(seq->buf);
+
+ seq->buf_len = seq->seq_len;
+ seq->buf = malloc(seq->buf_len);
+ }
+ seq->ra_offs = 0;
+
+ LOG (LOG_DEBUG, "buf_len: %d", seq->buf_len);
+ LOG (LOG_DEBUG, "cmd_off: %d", seq->cmd_offs);
+ }
+
+ if (seq->ra_offs < seq->buf_len) {
+ if (seq->ra_offs + pkt_len > seq->seq_len)
+ pkt_len = seq->seq_len - seq->ra_offs;
+
+ memcpy (seq->buf + seq->ra_offs, pkt_data, pkt_len);
+ seq->ra_offs += pkt_len;
+ }
+
+ if (seq->ra_offs == seq->seq_len) {
+ seq->finished = 0;
+ return 1; /* sequence ready */
+ }
+
+ return 0;
+}
+
+int spuNextEvent(spu_state_t *state, spu_seq_t* seq, int pts)
+{
+ uint8_t *buf = state->cmd_ptr;
+
+ if (state->next_pts == -1) { /* timestamp valid? */
+ state->next_pts = seq->PTS + ((buf[0] << 8) + buf[1]) * 1100;
+ buf += 2;
+ state->cmd_ptr = buf;
+ }
+
+ return state->next_pts <= pts;
+}
+
+#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
+
+void spuDoCommands(spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl)
+{
+ uint8_t *buf = state->cmd_ptr;
+ uint8_t *next_seq;
+
+ next_seq = seq->buf + (buf[0] << 8) + buf[1];
+ buf += 2;
+
+ if (state->cmd_ptr >= next_seq)
+ next_seq = seq->buf + seq->seq_len; /* allow to run until end */
+
+ state->cmd_ptr = next_seq;
+
+ while (buf < next_seq && *buf != CMD_SPU_EOF) {
+ switch (*buf) {
+ case CMD_SPU_SHOW: /* show subpicture */
+ LOG (LOG_DEBUG, "\tshow subpicture");
+ state->visible = 1;
+ buf++;
+ break;
+
+ case CMD_SPU_HIDE: /* hide subpicture */
+ LOG (LOG_DEBUG, "\thide subpicture");
+ state->visible = 0;
+ buf++;
+ break;
+
+ case CMD_SPU_SET_PALETTE: { /* CLUT */
+ spu_clut_t *clut = (spu_clut_t *) (buf+1);
+
+ ovl->color[3] = state->clut[clut->entry0];
+ ovl->color[2] = state->clut[clut->entry1];
+ ovl->color[1] = state->clut[clut->entry2];
+ ovl->color[0] = state->clut[clut->entry3];
+ LOG (LOG_DEBUG, "\tclut [%x %x %x %x]",
+ ovl->color[0], ovl->color[1], ovl->color[2], ovl->color[3]);
+ state->modified = 1;
+ buf += 3;
+ break;
+ }
+ case CMD_SPU_SET_ALPHA: { /* transparency palette */
+ spu_clut_t *trans = (spu_clut_t *) (buf+1);
+
+ /* TODO: bswap32? */
+ ovl->trans[3] = trans->entry0;
+ ovl->trans[2] = trans->entry1;
+ ovl->trans[1] = trans->entry2;
+ ovl->trans[0] = trans->entry3;
+ LOG (LOG_DEBUG, "\ttrans [%d %d %d %d]\n",
+ ovl->trans[0], ovl->trans[1], ovl->trans[2], ovl->trans[3]);
+ state->modified = 1;
+ buf += 3;
+ break;
+ }
+
+ case CMD_SPU_SET_SIZE: /* image coordinates */
+ state->o_left = (buf[1] << 4) | (buf[2] >> 4);
+ state->o_right = (((buf[2] & 0x0f) << 8) | buf[3]);
+
+ state->o_top = (buf[4] << 4) | (buf[5] >> 4);
+ state->o_bottom = (((buf[5] & 0x0f) << 8) | buf[6]);
+
+ LOG (LOG_DEBUG, "\ttop = %d bottom = %d left = %d right = %d",
+ state->o_left, state->o_right, state->o_top, state->o_bottom);
+ state->modified = 1;
+ buf += 7;
+ break;
+
+ case CMD_SPU_SET_PXD_OFFSET: /* image 1 / image 2 offsets */
+ state->field_offs[0] = (((u_int)buf[1]) << 8) | buf[2];
+ state->field_offs[1] = (((u_int)buf[3]) << 8) | buf[4];
+ LOG (LOG_DEBUG, "\toffset[0] = %d offset[1] = %d",
+ state->field_offs[0], state->field_offs[1]);
+ state->modified = 1;
+ buf += 5;
+ break;
+
+ case CMD_SPU_MENU:
+ state->menu = 1;
+ buf++;
+ break;
+
+ default:
+ fprintf(stderr, "libspudec: unknown seqence command (%02x)\n", buf[0]);
+ buf++;
+ break;
+ }
+ }
+ if (next_seq >= seq->buf + seq->seq_len)
+ seq->finished = 1; /* last sub-sequence */
+ state->next_pts = -1; /* invalidate timestamp */
+}
+
+static uint8_t *bit_ptr[2];
+static int field; // which field we are currently decoding
+static int put_x, put_y;
-static u_int _get_bits (u_int bits, vo_overlay_t *spu)
+static u_int get_bits (u_int bits)
{
static u_int data;
static u_int bits_left;
@@ -109,7 +251,7 @@ static u_int _get_bits (u_int bits, vo_overlay_t *spu)
ret |= data << (bits - bits_left);
bits -= bits_left;
- data = reassembly.buf[spu->offset[field]++];
+ data = *bit_ptr[field]++;
bits_left = 8;
} else {
bits_left -= bits;
@@ -122,236 +264,68 @@ static u_int _get_bits (u_int bits, vo_overlay_t *spu)
return ret;
}
-
-void spuInit (void)
-{
-}
-
-
-static inline void _spu_put_pixel (vo_overlay_t *spu, u_int len, uint8_t colorid)
+static inline void spu_put_pixel (vo_overlay_t *spu, 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);
+ memset (spu->data + put_x + put_y * spu->width, colorid, len);
+ put_x += len;
}
-
-static int _spu_next_line (vo_overlay_t *spu)
+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
+ get_bits (0); // byte align rle data
- 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) {
- reassembly.buf = pkt_data;
- reassembly_flag = REASSEMBLY_UNNEEDED;
- return &reassembly;
- } else {
- 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 {
- 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;
- }
- }
+ put_x = 0;
+ put_y++;
+ field ^= 1; // Toggle fields
- 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)))
+ if (put_y >= spu->height) {
+ LOG (LOG_DEBUG, ".");
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 = /* Frames + */ ((buf[i] << 8) + buf[i+1]) /* * TIME_UNIT */ ;
- LOG (LOG_DEBUG, "duration = %d frames", 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[3] = clut->entry0;
- spu->clut[2] = clut->entry1;
- spu->clut[1] = clut->entry2;
- spu->clut[0] = 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 */
- 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;
- 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 */
-
- if (spu->data) spu->data = (uint8_t *) realloc (spu->data,spu->width * spu->height * sizeof (uint8_t));
- else 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
- */
- 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)
+void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl)
{
field = 0;
- _get_bits (0, spu); /* Reset/init bit code */
-
- while ((spu->offset[1] < reassembly.cmd_offset)) {
+ bit_ptr[0] = seq->buf + state->field_offs[0];
+ bit_ptr[1] = seq->buf + state->field_offs[1];
+ put_x = put_y = 0;
+ get_bits (0); /* Reset/init bit code */
+
+ ovl->x = state->o_left;
+ ovl->y = state->o_top;
+ ovl->width = state->o_right - state->o_left;
+ ovl->height = state->o_bottom - state->o_top;
+
+ ovl->clip_top = 0;
+ ovl->clip_bottom = ovl->height;
+ ovl->clip_left = 0;
+ ovl->clip_right = ovl->width;
+
+ spuUpdateMenu(state, ovl);
+
+ if (ovl->width * ovl->height > ovl->data_size) {
+ if (ovl->data)
+ free(ovl->data);
+ ovl->data_size = ovl->width * ovl->height;
+ ovl->data = malloc(ovl->data_size);
+ }
+
+ state->modified = 0; /* mark as already processed */
+
+ while (bit_ptr[1] < seq->buf + seq->cmd_offs) {
u_int len;
u_int color;
u_int vlc;
- vlc = _get_bits (4, spu);
+ vlc = get_bits (4);
if (vlc < 0x0004) {
- vlc = (vlc << 4) | _get_bits (4, spu);
+ vlc = (vlc << 4) | get_bits (4);
if (vlc < 0x0010) {
- vlc = (vlc << 4) | _get_bits (4, spu);
+ vlc = (vlc << 4) | get_bits (4);
if (vlc < 0x0040) {
- vlc = (vlc << 4) | _get_bits (4, spu);
+ vlc = (vlc << 4) | get_bits (4);
}
}
}
@@ -360,26 +334,47 @@ void spuParseData (vo_overlay_t *spu)
len = vlc>>2;
/* if len == 0 -> end sequence - fill to end of line */
- len = len ? : spu->width - spu->_x;
+ if (!len)
+ len = ovl->width - put_x;
- _spu_put_pixel (spu, len, color);
+ spu_put_pixel (ovl, len, color);
- if (spu->_x >= spu->width)
- if (_spu_next_line (spu) < 0)
- goto clean_up;
+ if (put_x >= ovl->width)
+ if (spu_next_line (ovl) < 0)
+ return;
}
/* 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);
- }
+ do {
+ spu_put_pixel (ovl, ovl->width, 0);
+ } while (!spu_next_line (ovl));
+}
- clean_up:
- if (reassembly_flag != REASSEMBLY_UNNEEDED) {
- LOG (LOG_DEBUG, "freeing reassembly.buf");
- free (reassembly.buf);
- }
+void spuUpdateMenu (spu_state_t *state, vo_overlay_t *ovl) {
+
+ if (!state->menu)
+ return;
+
+ if (state->b_show) {
+
+ int left = state->b_left;
+ int right = state->b_right;
+ int top = state->b_top;
+ int bottom = state->b_bottom;
+
+ if (left < state->o_left) left = state->o_left;
+ if (right > state->o_right) right = state->o_right;
+ if (top < state->o_top) top = state->o_top;
+ if (bottom > state->o_bottom) bottom = state->o_bottom;
+
+ ovl->clip_top = top - state->o_top;
+ ovl->clip_bottom = bottom - state->o_top;
+ ovl->clip_left = left - state->o_left;
+ ovl->clip_right = right - state->o_left;
+
+ state->visible = 1;
- reassembly_flag = REASSEMBLY_START;
+ } else {
+ state->visible = 0;
+ }
}
diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h
index 09cfd32ee..6899c7af8 100644
--- a/src/libspudec/spu.h
+++ b/src/libspudec/spu.h
@@ -19,7 +19,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: spu.h,v 1.2 2001/07/04 20:32:29 uid32519 Exp $
+ * $Id: spu.h,v 1.3 2001/08/13 12:52:33 ehasenle Exp $
*
* This file was originally part of the OMS program.
*
@@ -59,11 +59,40 @@ typedef struct spu_clut_struct {
#endif
} spu_clut_t;
+typedef struct {
+ uint8_t *buf;
+ u_int ra_offs; /* reassembly offset */
+ u_int seq_len;
+ u_int buf_len;
-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);
+ u_int cmd_offs;
+
+ u_int PTS; /* Base PTS of this sequence */
+ int finished; /* Has this sequence been finished? */
+} spu_seq_t;
+
+typedef struct {
+ uint8_t *cmd_ptr;
+
+ int field_offs[2];
+ int b_top, o_top;
+ int b_bottom, o_bottom;
+ int b_left, o_left;
+ int b_right, o_right;
+
+ u_int next_pts; /* pts of next sub-sequence */
+ int modified; /* Was the sub-picture modified? */
+ int visible; /* Must the sub-picture be shown? */
+ int menu; /* This overlay is a menu */
+ int b_show; /* is a button shown? */
+
+ uint32_t clut[16];
+} spu_state_t;
+
+int spuReassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len);
+int spuNextEvent (spu_state_t *state, spu_seq_t* seq, int pts);
+void spuDoCommands (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
+void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
+void spuUpdateMenu (spu_state_t *state, vo_overlay_t *ovl);
#endif
diff --git a/src/libspudec/spu_decoder_api.h b/src/libspudec/spu_decoder_api.h
index e30a4cd11..a7d75511a 100644
--- a/src/libspudec/spu_decoder_api.h
+++ b/src/libspudec/spu_decoder_api.h
@@ -44,6 +44,8 @@ struct spu_decoder_s {
void (*decode_data) (spu_decoder_t *this, buf_element_t *buf);
+ void (*event) (spu_decoder_t *this, spu_event_t *event);
+
void (*close) (spu_decoder_t *this);
char* (*get_identifier) (void);
@@ -70,4 +72,20 @@ struct spudec_s {
};
+#define SPU_EVENT_BUTTON 0x100
+typedef struct spu_button_s spu_button_t;
+struct spu_button_s {
+ int show;
+ uint8_t color[4];
+ uint8_t trans[4];
+ int left, right;
+ int top, bottom;
+};
+
+#define SPU_EVENT_CLUT 0x101
+typedef struct spu_cltbl_s spu_cltbl_t;
+struct spu_cltbl_s {
+ uint32_t clut[16];
+};
+
#endif /* HAVE_SPUDEC_H */
diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c
index 406c0cc9d..0d3a0836d 100644
--- a/src/libspudec/xine_decoder.c
+++ b/src/libspudec/xine_decoder.c
@@ -19,7 +19,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_decoder.c,v 1.7 2001/08/05 08:24:56 ehasenle Exp $
+ * $Id: xine_decoder.c,v 1.8 2001/08/13 12:52:33 ehasenle Exp $
*
* stuff needed to turn libspu into a xine decoder plugin
*/
@@ -38,31 +38,48 @@
#include "spu.h"
#include "buffer.h"
+#include "events.h"
#include "xine_internal.h"
-#define FRAME_SIZE 4096
-
+static clut_t __default_clut[] = {
+ {y: 0x00, cr: 0x80, cb:0x80},
+ {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: 0xbf, cr: 0x80, cb:0x80},
+ {y: 0x51, 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}
+};
+
+#define NUM_SEQ_BUFFERS 5
typedef struct spudec_decoder_s {
spu_decoder_t spu_decoder;
+ ovl_src_t ovl_src;
- uint32_t pts;
+ spu_seq_t seq_list[NUM_SEQ_BUFFERS];
+ spu_seq_t *cur_seq;
+ spu_seq_t *ra_seq;
+ int ra_complete;
- uint8_t frame_buffer[FRAME_SIZE];
- uint8_t *frame_ptr;
- int sync_todo;
- int frame_length, frame_todo;
- uint16_t syncword;
+ uint32_t ovl_pts;
+ uint32_t buf_pts;
+ spu_state_t state;
vo_instance_t *vo_out;
- vo_overlay_t *spu;
- uint32_t *clut;
- int spu_caps;
- int bypass_mode;
- int max_num_channels;
- int output_sampling_rate;
+ vo_overlay_t ovl;
+ int ovl_caps;
int output_open;
- int output_mode;
} spudec_decoder_t;
@@ -71,107 +88,155 @@ int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT) ;
}
+static void spudec_reset (spudec_decoder_t *this) {
+ int i;
+
+ this->ovl_pts = 0;
+ this->buf_pts = 0;
+
+ this->state.visible = 0;
+
+ for (i = 0; i < NUM_SEQ_BUFFERS; i++) {
+ this->seq_list[i].finished = 1;
+ }
+ this->ra_complete = 1;
+ this->cur_seq = this->ra_seq = this->seq_list;
+}
+
void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+
this->vo_out = vo_out;
- this->spu_caps = vo_out->get_capabilities(vo_out);
- this->syncword = 0;
- this->sync_todo = 6;
+ this->ovl_caps = vo_out->get_capabilities(vo_out);
this->output_open = 0;
-}
-
-/* overlay_txt is just for test purposes */
-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;
+ spudec_reset(this);
+ memcpy(this->state.clut, __default_clut, sizeof(this->state.clut));
+ vo_out->register_ovl_src(vo_out, &this->ovl_src);
}
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;
-
if (buf->type == BUF_SPU_CLUT) {
- if (this->clut == NULL)
- this->clut = malloc(sizeof(clut_t)*16);
-
- memcpy(this->clut, buf->content, sizeof(clut_t)*16);
+ memcpy(this->state.clut, buf->content, sizeof(int32_t)*16);
return;
}
-
- 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 (buf->PTS) {
+ metronom_t *metronom = this->ovl_src.metronom;
+ uint32_t pts = metronom->got_spu_packet(metronom, buf->PTS, 0);
+ if (pts < this->buf_pts)
+ spudec_reset(this);
- this->spu->PTS = buf->PTS;
- if (this->clut)
- this->spu->clut_tbl = this->clut;
-
- if (!spuParseHdr (this->spu, current, buf->size)) {
- spuParseData (this->spu);
- /* overlay_txt(this->spu,1.0); Just for test purposes */
- this->vo_out->queue_overlay (this->vo_out, this->spu);
- this->spu = NULL;
- } else {
- this->spu->data=NULL;
- this->vo_out->queue_overlay (this->vo_out, this->spu);
- this->spu = NULL;
+ this->buf_pts = pts;
+ }
+
+ if (this->ra_complete) {
+ spu_seq_t *tmp_seq = this->ra_seq + 1;
+ if (tmp_seq >= this->seq_list + NUM_SEQ_BUFFERS)
+ tmp_seq = this->seq_list;
+
+ if (tmp_seq->finished) {
+ this->ra_seq = tmp_seq;
+ this->ra_seq->PTS = this->buf_pts;
+ }
}
+ this->ra_complete =
+ spuReassembly(this->ra_seq, this->ra_complete, buf->content, buf->size);
}
void spudec_close (spu_decoder_t *this_gen) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+
+ this->vo_out->unregister_ovl_src(this->vo_out, &this->ovl_src);
+}
- if (this->clut) {
- free(this->clut);
- this->clut = 0;
+static void spudec_nextseq(spudec_decoder_t* this) {
+ spu_seq_t *tmp_seq = this->cur_seq + 1;
+ if (tmp_seq >= this->seq_list + NUM_SEQ_BUFFERS)
+ tmp_seq = this->seq_list;
+
+ if (!tmp_seq->finished) { /* is the next seq ready for process? */
+ this->cur_seq = tmp_seq;
+ this->state.cmd_ptr = this->cur_seq->buf + this->cur_seq->cmd_offs;
+ this->state.next_pts = -1; /* invalidate timestamp */
+ this->state.modified = 1;
+ this->state.visible = 0;
+ this->state.menu = 0;
}
+}
+
+static vo_overlay_t* spudec_get_overlay(ovl_src_t *ovl_src, int pts) {
+ spudec_decoder_t *this = (spudec_decoder_t*) ovl_src->src_gen;
+ int pending = 0;
-/* FIXME not implemented */
-// if (this->output_open)
-// this->spu_out->close (this->spu_out);
+ if (this->ovl_pts > pts)
+ spudec_reset(this);
- /* close (spufile); */
+ this->ovl_pts = pts;
+
+ do {
+ if (this->cur_seq->finished)
+ spudec_nextseq(this);
+
+ if (!this->cur_seq->finished) {
+ pending = spuNextEvent(&this->state, this->cur_seq, pts);
+
+ if (pending)
+ spuDoCommands(&this->state, this->cur_seq, &this->ovl);
+ } else
+ pending = 0;
+
+ } while (pending);
+
+ if (this->state.visible) {
+ if (this->state.modified) {
+ spuDrawPicture(&this->state, this->cur_seq, &this->ovl);
+ }
+
+ return &this->ovl;
+ }
+
+ return NULL;
+}
+
+static void spudec_event(spu_decoder_t *this_gen, spu_event_t *event) {
+ spudec_decoder_t *this = (spudec_decoder_t*) this_gen;
+
+ switch (event->sub_type) {
+ case SPU_EVENT_BUTTON:
+ {
+ spu_button_t *but = event->data;
+ if (!this->state.menu) return;
+
+ if (but->show) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ this->ovl.color[i] = this->state.clut[but->color[i]];
+ this->ovl.trans[i] = but->trans[i];
+ }
+
+ this->state.b_left = but->left;
+ this->state.b_right = but->right;
+ this->state.b_top = but->top;
+ this->state.b_bottom = but->bottom;
+ }
+
+ this->state.b_show = but->show;
+ spuUpdateMenu(&this->state, &this->ovl);
+ }
+ break;
+ case SPU_EVENT_CLUT:
+ {
+ spu_cltbl_t *clut = event->data;
+ memcpy(this->state.clut, clut->clut, sizeof(int32_t)*16);
+ }
+ break;
+ }
}
static char *spudec_get_id(void) {
@@ -182,18 +247,28 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, config_values_t *cfg)
spudec_decoder_t *this ;
- if (iface_version != 2)
+ if (iface_version != 3) {
+ fprintf(stderr,
+ "libspudec: Doesn't support plugin API version %d.\n"
+ "libspudec: This means there is a version mismatch between XINE and\n"
+ "libspudec: this plugin.\n", iface_version);
return NULL;
+ }
this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t));
+ memset (this, 0, sizeof(*this));
- this->spu_decoder.interface_version = 2;
+ this->spu_decoder.interface_version = 3;
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.event = spudec_event;
this->spu_decoder.close = spudec_close;
this->spu_decoder.get_identifier = spudec_get_id;
this->spu_decoder.priority = 1;
+
+ this->ovl_src.src_gen = this;
+ this->ovl_src.get_overlay = spudec_get_overlay;
return (spu_decoder_t *) this;
}
diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c
index e0d6c075e..b8a540b2a 100644
--- a/src/video_out/alphablend.c
+++ b/src/video_out/alphablend.c
@@ -138,10 +138,10 @@ void blend_tux_rgb16 (uint8_t * img, int dst_width, int dst_height)
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]; \
+ o = img_overl->trans[*src]; \
\
- if ((*src) >> 4 & 0xf) /* if alpha is != 0 */ \
- *dst = blendpixel_rgb##bpp (*dst, myclut[img_overl->clut[(*src&0x0f)]], o); \
+ if (o) /* if alpha is != 0 */ \
+ *dst = blendpixel_rgb##bpp (*dst, myclut[*src], o); \
src++; \
dst++; \
} \
@@ -256,9 +256,10 @@ static clut_t __default_clut[] = {
};
void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl,
- int dst_width, int dst_height)
+ int dst_width, int dst_height)
{
clut_t *my_clut;
+ uint8_t *my_trans;
int src_width = img_overl->width;
int src_height = img_overl->height;
@@ -275,36 +276,36 @@ void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl,
int x, y;
- /* If there is a CLUT palette specified, use it instead. */
- if(img_overl->clut_tbl != NULL) {
- my_clut = (clut_t*)img_overl->clut_tbl;
- } else {
- my_clut = __default_clut;
- }
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
for (y = 0; y < src_height; y++) {
for (x = 0; x < src_width; x++) {
uint8_t clr;
- uint8_t mask;
uint16_t o;
- mask = (*src_data) >> 4 ;
+ clr = *src_data & 3;
+ o = my_trans[clr];
+
+ /* OK, this looks time consuming.
+ * But it gets only evaluated if (o != 0) */
+ if (o) if (img_overl->clip_left > x ||
+ img_overl->clip_right <= x ||
+ img_overl->clip_top > y ||
+ img_overl->clip_bottom <= y)
+ o = 0;
- clr = img_overl->clut[*src_data & 0x03];
- o = img_overl->trans[*src_data & 0x03];
- if(o)
- *dst_y = BLEND_YUV (*dst_y, my_clut[clr].y, o);
+ if (o)
+ *dst_y = BLEND_YUV (*dst_y, my_clut[clr].y, o);
dst_y++;
if (y & x & 1) {
- if (mask) {
- if(o) {
- *dst_cr = BLEND_YUV (*dst_cr, my_clut[clr].cr, o);
- *dst_cb = BLEND_YUV (*dst_cb, my_clut[clr].cb, o);
- }
+ if(o) {
+ *dst_cr = BLEND_YUV (*dst_cr, my_clut[clr].cr, o);
+ *dst_cb = BLEND_YUV (*dst_cb, my_clut[clr].cb, o);
}
- dst_cr++;
- dst_cb++;
+ dst_cr++;
+ dst_cb++;
}
src_data++;
}
diff --git a/src/xine-engine/events.h b/src/xine-engine/events.h
index 19db8b618..a1ec552f5 100644
--- a/src/xine-engine/events.h
+++ b/src/xine-engine/events.h
@@ -63,6 +63,16 @@ typedef struct overlay_event_s {
vo_overlay_t overlay;
} overlay_event_t;
+/**
+ * SPU event - send control events to the spu decoder
+ */
+#define XINE_SPU_EVENT 0x0003
+typedef struct spu_event_s {
+ event_t event;
+ int sub_type;
+ void *data;
+} spu_event_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index d15622143..3e18c944b 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.35 2001/07/30 17:13:22 guenter Exp $
+ * $Id: load_plugins.c,v 1.36 2001/08/13 12:52:33 ehasenle Exp $
*
*
* Load input/demux/audio_out/video_out/codec plugins
@@ -371,7 +371,7 @@ void load_decoder_plugins (xine_t *this,
spu_decoder_t *sdp;
int streamtype;
- sdp = (spu_decoder_t *) initplug(iface_version, config);
+ sdp = (spu_decoder_t *) initplug(3, config);
if (sdp) {
sdp->metronom = this->metronom;
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 1a01d8cc6..93f6766de 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.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.c,v 1.38 2001/08/05 08:24:56 ehasenle Exp $
+ * $Id: video_out.c,v 1.39 2001/08/13 12:52:33 ehasenle Exp $
*
*/
@@ -140,8 +140,6 @@ static void *video_out_loop (void *this_gen) {
uint32_t cur_pts;
int pts_absdiff, diff, absdiff, pts=0;
vo_frame_t *img;
- vo_overlay_t *overlay;
- int count;
uint32_t video_step, video_step_new;
vo_instance_t *this = (vo_instance_t *) this_gen;
sigset_t vo_mask;
@@ -276,65 +274,19 @@ static void *video_out_loop (void *this_gen) {
xprintf (VERBOSE|VIDEO, "video_out : passing to video driver, image with pts = %d\n", pts);
-
- overlay=this->first_overlay;
- while (overlay) {
- if(overlay->state==OVERLAY_SHOWING) {
- if (this->driver->overlay_blend) this->driver->overlay_blend (this->driver, img, overlay);
- }
- overlay=overlay->next;
+ if (this->overlay_source) {
+ /* This is the only way for the spu decoder to get pts values
+ * for flushing it's buffers. So don't remove it! */
+ vo_overlay_t *ovl =
+ this->overlay_source->get_overlay (this->overlay_source, img->PTS);
+ if (ovl && this->driver->overlay_blend)
+ this->driver->overlay_blend (this->driver, img, ovl);
}
this->driver->display_frame (this->driver, img);
- /* Control Overlay SHOW/HIDE based on PTS */
- overlay=this->first_overlay;
- count=1;
- while (overlay) {
- switch(overlay->state) {
- case OVERLAY_FREE:
- break;
- case OVERLAY_CREATING:
- break;
- case OVERLAY_READY_TO_SHOW:
- if (cur_pts>overlay->PTS) overlay->state=OVERLAY_SHOWING;
- if (abs(cur_pts-overlay->PTS) > pts_absdiff ) overlay->state=OVERLAY_READY_TO_FREE;
- break;
- case OVERLAY_SHOWING:
- /* duration is in frames, Who knows why div 4 ? */
- if ((cur_pts>overlay->PTS+(overlay->duration*video_step/4))) overlay->state=OVERLAY_READY_TO_FREE;
- break;
- case OVERLAY_READY_TO_FREE:
- /* remove overlay from list */
- if (overlay->next) {
- if (overlay->priv)
- overlay->priv->next=overlay->next;
- else
- this->first_overlay=overlay->next;
- overlay->next->priv=overlay->priv;
- } else {
- overlay->state=OVERLAY_FREE;
- break;
- }
- /* Set status to free */
- overlay->state=OVERLAY_FREE;
- /* Insert at end of list */
- overlay->priv=this->last_overlay;
- this->last_overlay->next=overlay;
- overlay->next=NULL;
- this->last_overlay=overlay;
- break;
- default:
- printf("OVERLAY in UNKNOWN state\n");
- }
- overlay=overlay->next;
- }
-
}
-
-
-
/*
* throw away undisplayed frames
*/
@@ -365,15 +317,6 @@ static void vo_open (vo_instance_t *this) {
if (!this->video_loop_running) {
this->video_loop_running = 1;
- if(this->first_overlay) {
- vo_overlay_t *overlay;
- overlay=this->first_overlay;
- while (overlay) {
- overlay->state=OVERLAY_FREE;
- overlay->clut_tbl=NULL;
- overlay=overlay->next;
- }
- }
pthread_create (&this->video_thread, NULL, video_out_loop, this) ;
printf ("video_out: thread created\n");
@@ -558,57 +501,17 @@ static int vo_frame_draw (vo_frame_t *img) {
return frames_to_skip;
}
-/****************************************************************
- * Current assumption is that only one thread will call vo_get_overlay at a time
- * Also mutex locks have not yet been considered or used
- * Also, when one is FREEed, it is moved to the end of the queue, so it will be the first one used
- * The design is based around a dynamic buffer size.
- * The buffer starts at nothing, then increases as needed.
- * If a buffer entry is free, it will be reused.
- * If all buffers are full, xmalloc is called.
- * FIXME: Can someone make this simpler ? It seems a bit long winded to me.
- ***************************************************************/
-static vo_overlay_t *vo_get_overlay (vo_instance_t *this) {
- vo_overlay_t *next_overlay;
- vo_overlay_t *prev_overlay;
- int count_overlay=0;
- if (this->first_overlay==NULL) {
- this->first_overlay = this->last_overlay = xmalloc (sizeof (vo_overlay_t)) ;
- this->first_overlay->data=NULL;
- this->first_overlay->clut_tbl=NULL;
- this->first_overlay->next=NULL;
- this->first_overlay->priv=NULL;
- this->first_overlay->state=OVERLAY_CREATING;
- count_overlay++;
- return this->first_overlay;
- }
- prev_overlay=this->first_overlay;
- next_overlay=this->first_overlay->next;
- while (next_overlay && (prev_overlay->state!=OVERLAY_FREE)) {
- count_overlay++;
- prev_overlay=next_overlay;
- next_overlay=prev_overlay->next;
- }
- if (prev_overlay->state==OVERLAY_FREE) {
- prev_overlay->state=OVERLAY_CREATING;
- return prev_overlay;
- }
- prev_overlay->next = next_overlay = this->last_overlay = xmalloc (sizeof (vo_overlay_t)) ;
- count_overlay++;
- next_overlay->data=NULL;
- next_overlay->next=NULL;
- next_overlay->priv=prev_overlay;
- next_overlay->state=OVERLAY_CREATING;
- return next_overlay;
+static void vo_register_ovl_src (vo_instance_t *this, ovl_src_t *ovl_src)
+{
+ this->overlay_source = ovl_src;
+ ovl_src->metronom = this->metronom;
}
-static void vo_queue_overlay (vo_instance_t *this, vo_overlay_t *overlay) {
- overlay->PTS = this->metronom->got_spu_packet (this->metronom, overlay->PTS,overlay->duration);
- if (overlay->data==NULL) {
- overlay->state=OVERLAY_FREE;
- } else {
- overlay->state=OVERLAY_READY_TO_SHOW;
- }
+static void vo_unregister_ovl_src (vo_instance_t *this, ovl_src_t *ovl_src)
+{
+ /* only remove the source if it is the same as registered */
+ if (this->overlay_source == ovl_src)
+ this->overlay_source = NULL;
}
vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) {
@@ -617,8 +520,6 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) {
int i;
this = xmalloc (sizeof (vo_instance_t)) ;
- this->first_overlay=NULL;
- this->last_overlay=NULL;
this->driver = driver;
this->metronom = metronom;
@@ -627,8 +528,8 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) {
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->register_ovl_src = vo_register_ovl_src;
+ this->unregister_ovl_src = vo_unregister_ovl_src;
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 0e9c366d8..fbe2b9c60 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.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: video_out.h,v 1.15 2001/07/25 23:26:14 richwareham Exp $
+ * $Id: video_out.h,v 1.16 2001/08/13 12:52:33 ehasenle Exp $
*
*
* xine version of video_out.h
@@ -95,6 +95,13 @@ struct vo_frame_s {
void (*dispose) (vo_frame_t *vo_img);
};
+typedef struct ovl_src_s ovl_src_t;
+
+struct ovl_src_s {
+ void *src_gen;
+ vo_overlay_t* (*get_overlay) (ovl_src_t* self, int pts);
+ metronom_t* metronom;
+};
struct vo_instance_s {
@@ -119,8 +126,9 @@ struct vo_instance_s {
int flags);
/* overlay stuff */
- vo_overlay_t* (*get_overlay) (vo_instance_t *this);
- void (*queue_overlay) (vo_instance_t *this, vo_overlay_t *overlay);
+ void (*register_ovl_src) (vo_instance_t *this, ovl_src_t *ovl_src);
+ void (*unregister_ovl_src) (vo_instance_t *this, ovl_src_t *ovl_src);
+ ovl_src_t *overlay_source;
/* video driver is no longer used by decoder => close */
void (*close) (vo_instance_t *this);
@@ -131,8 +139,6 @@ struct vo_instance_s {
/* private stuff */
vo_driver_t *driver;
- vo_overlay_t *first_overlay;
- vo_overlay_t *last_overlay;
metronom_t *metronom;
img_buf_fifo_t *free_img_buf_queue;
@@ -257,34 +263,22 @@ struct vo_driver_s {
};
-#define OVERLAY_FREE 0
-#define OVERLAY_CREATING 1
-#define OVERLAY_READY_TO_SHOW 2
-#define OVERLAY_SHOWING 3
-#define OVERLAY_READY_TO_FREE 4
-
struct vo_overlay_s {
uint8_t *data; /* 7-4: mixer key, 3-0: color index */
+ int data_size; /* useful for deciding realloc */
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 */
+ uint32_t color[4]; /* color lookup table */
uint8_t trans[4]; /* mixer key table */
-
- uint32_t PTS, duration; /* 1/90000 s */
- vo_overlay_t *next; /* optionally more overlays */
- vo_overlay_t *priv; /* optionally more overlays */
- int state; /* State:FREE,SHOWING etc. */
-
- uint32_t *clut_tbl; /* Pointer to CLUT palette */
-
- /* 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 */
+ int clip_top;
+ int clip_bottom;
+ int clip_left;
+ int clip_right;
+
};
/*
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 864641e6d..6123aa18d 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.39 2001/08/12 15:12:54 guenter Exp $
+ * $Id: xine.c,v 1.40 2001/08/13 12:52:33 ehasenle Exp $
*
* top-level xine functions
*
@@ -50,6 +50,7 @@
#include "libw32dll/w32codec.h"
#endif
#include "libspudec/spu_decoder_api.h"
+/* TODO: who uses spu_decoder.h ? */
#include "spu_decoder.h"
#include "input/input_plugin.h"
#include "metronom.h"
@@ -389,29 +390,10 @@ static void event_handler(xine_t *xine, event_t *event, void *data) {
}
}
break;
- case XINE_OVERLAY_EVENT:
- {
- overlay_event_t *oevent = (overlay_event_t*)event;
- if(xine->video_out != NULL) {
- int i;
- vo_overlay_t *overlay = xine->video_out->get_overlay (xine->video_out);
- if(overlay != NULL) {
- overlay->data = oevent->overlay.data;
- overlay->x = oevent->overlay.x;
- overlay->y = oevent->overlay.y;
- overlay->width = oevent->overlay.width;
- overlay->height = oevent->overlay.height;
- for(i=0; i<4; i++) {
- overlay->clut[i] = oevent->overlay.clut[i];
- overlay->trans[i] = oevent->overlay.trans[i];
- }
- overlay->PTS = oevent->overlay.PTS;
- overlay->clut_tbl = oevent->overlay.clut_tbl;
- overlay->duration = oevent->overlay.duration;
- xine->video_out->queue_overlay (xine->video_out, overlay);
- }
- }
- }
+ case XINE_SPU_EVENT:
+ if (xine->cur_spu_decoder_plugin)
+ xine->cur_spu_decoder_plugin->event(xine->cur_spu_decoder_plugin,
+ (spu_event_t*) event);
break;
}
}
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 55a4c1ad9..0833438c5 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.36 2001/07/30 17:13:22 guenter Exp $
+ * $Id: xine_internal.h,v 1.37 2001/08/13 12:52:33 ehasenle Exp $
*
*/
@@ -36,8 +36,8 @@ extern "C" {
#include "audio_out.h"
#include "metronom.h"
#include "spu_decoder.h"
-#include "libspudec/spu_decoder_api.h"
#include "events.h"
+#include "libspudec/spu_decoder_api.h"
#define INPUT_PLUGIN_MAX 50
#define DEMUXER_PLUGIN_MAX 50