summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2002-06-24 15:49:32 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2002-06-24 15:49:32 +0000
commit9f169bfef3229a9c2b2396993e2fcea1b3a7c8ac (patch)
tree5bf7346e1d1b6d4b2edc3c4335f17e0da095fb25 /src
parent77a7de7e0eb0598b3283269a0f79fd22b102fde0 (diff)
downloadxine-lib-9f169bfef3229a9c2b2396993e2fcea1b3a7c8ac.tar.gz
xine-lib-9f169bfef3229a9c2b2396993e2fcea1b3a7c8ac.tar.bz2
Add a correction for spus during menus that contain a display
duration entry. This confuses the card because the spu should be hidden when the menu is left, not by timeout. Therefore we kill such an entry in menu spus. CVS patchset: 2154 CVS date: 2002/06/24 15:49:32
Diffstat (limited to 'src')
-rw-r--r--src/dxr3/dxr3_decode_spu.c123
1 files changed, 96 insertions, 27 deletions
diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c
index 6b3a37d47..4dfccaade 100644
--- a/src/dxr3/dxr3_decode_spu.c
+++ b/src/dxr3/dxr3_decode_spu.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: dxr3_decode_spu.c,v 1.5 2002/06/12 15:09:07 mroi Exp $
+ * $Id: dxr3_decode_spu.c,v 1.6 2002/06/24 15:49:32 mroi Exp $
*/
/* dxr3 spu decoder plugin.
@@ -63,15 +63,15 @@ static void dxr3_spudec_reset(spu_decoder_t *this_gen);
static void dxr3_spudec_close(spu_decoder_t *this_gen);
static void dxr3_spudec_dispose(spu_decoder_t *this_gen);
-/* helper functions */
-static int dxr3_present(xine_t *xine);
-static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen);
-static int dxr3_spudec_copy_nav_to_btn(pci_t *nav_pci, int32_t button, int32_t mode, em8300_button_t *btn);
-static void dxr3_swab_clut(int* clut);
-
/* plugin structures */
typedef struct dxr3_spu_stream_state_s {
uint32_t stream_filter;
+
+ int spu_length;
+ int spu_ctrl;
+ int spu_end;
+ int end_found;
+ int bytes_passed; /* used to parse the spu */
} dxr3_spu_stream_state_t;
typedef struct dxr3_spudec_s {
@@ -81,14 +81,20 @@ typedef struct dxr3_spudec_s {
char devname[128];
char devnum[3];
- int fd_spu; /* to access the dxr3 spu device */
+ int fd_spu; /* to access the dxr3 spu device */
dxr3_spu_stream_state_t spu_stream_state[MAX_SPU_STREAMS];
- int menu; /* are we in a menu? */
+ int menu; /* are we in a menu? */
pci_t pci;
- uint32_t buttonN; /* currently highlighted button */
+ uint32_t buttonN; /* currently highlighted button */
} dxr3_spudec_t;
+/* helper functions */
+static int dxr3_present(xine_t *xine);
+static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen);
+static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300_button_t *btn);
+static void dxr3_swab_clut(int* clut);
+
spu_decoder_t *init_spu_decoder_plugin(int iface_version, xine_t *xine)
{
@@ -175,8 +181,10 @@ static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out)
#if LOG_SPU
printf ("dxr3_decode_spu: init: SPU_FD = %i\n",this->fd_spu);
#endif
- for (i=0; i < MAX_SPU_STREAMS; i++) /* reset the spu filter for non-dvdnav */
+ for (i=0; i < MAX_SPU_STREAMS; i++) {
this->spu_stream_state[i].stream_filter = 1;
+ this->spu_stream_state[i].spu_length = 0;
+ }
}
static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
@@ -184,6 +192,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
ssize_t written;
uint32_t stream_id = buf->type & 0x1f;
+ dxr3_spu_stream_state_t *state = &this->spu_stream_state[stream_id];
if (buf->type == BUF_SPU_CLUT) {
#if LOG_SPU
@@ -223,10 +232,11 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
/* menu ahead, remember pci for later evaluation */
xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
- if ((dxr3_spudec_copy_nav_to_btn(&this->pci, this->buttonN, 0, &btn ) > 0))
+ if ((dxr3_spudec_copy_nav_to_btn(this, 0, &btn ) > 0))
if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn))
printf("dxr3_decode_spu: failed to set spu button (%s)\n",
strerror(errno));
+ this->menu = 1;
}
if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) {
@@ -240,52 +250,97 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
0x00, 0x01, 0x00, 0x20, 0x02, 0xFF };
/* leaving menu */
this->pci.hli.hl_gi.hli_ss = 0;
+ this->menu = 0;
ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL);
write(this->fd_spu, empty_spu, sizeof(empty_spu));
}
}
return;
}
+
+ /* Look for the display duration entry in the spu packets.
+ * If the spu is a menu button highlight pane, this entry must not exist,
+ * because the spu is hidden, when the menu is left, not by timeout.
+ * Some broken dvds do not respect this and therefore confuse the spu
+ * decoding pipeline of the card. We fix this here.
+ */
+ if (!state->spu_length) {
+ state->spu_length = buf->content[0] << 8 | buf->content[1];
+ state->spu_ctrl = (buf->content[2] << 8 | buf->content[3]) + 2;
+ state->spu_end = 0;
+ state->end_found = 0;
+ state->bytes_passed = 0;
+ }
+ if (!state->end_found) {
+ int offset_in_buffer = state->spu_ctrl - state->bytes_passed;
+ if (offset_in_buffer >= 0 && offset_in_buffer < buf->size)
+ state->spu_end = buf->content[offset_in_buffer] << 8;
+ offset_in_buffer++;
+ if (offset_in_buffer >= 0 && offset_in_buffer < buf->size) {
+ state->spu_end |= buf->content[offset_in_buffer];
+ state->end_found = 1;
+ }
+ }
+ if (state->end_found && this->menu) {
+ int offset_in_buffer = state->spu_end - state->bytes_passed;
+ if (offset_in_buffer >= 0 && offset_in_buffer < buf->size)
+ buf->content[offset_in_buffer] = 0x00;
+ offset_in_buffer++;
+ if (offset_in_buffer >= 0 && offset_in_buffer < buf->size)
+ buf->content[offset_in_buffer] = 0x00;
+ offset_in_buffer += 3;
+ if (offset_in_buffer >= 0 && offset_in_buffer < buf->size &&
+ buf->content[offset_in_buffer] == 0x02)
+ buf->content[offset_in_buffer] = 0x00;
+ }
+ state->spu_length -= buf->size;
+ if (state->spu_length < 0) state->spu_length = 0;
+ state->bytes_passed += buf->size;
+
+ /* filter unwanted streams */
if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
#if LOG_SPU
printf("dxr3_decode_spu: Dropping SPU channel %d. Preview data\n", stream_id);
#endif
return;
}
-
- if (this->spu_stream_state[stream_id].stream_filter == 0) {
+ if (state->stream_filter == 0) {
#if LOG_SPU
printf("dxr3_decode_spu: Dropping SPU channel %d. Stream filtered\n", stream_id);
#endif
return;
}
- if ((this->xine->spu_channel & 0x1f) != stream_id ) {
+ if ((this->xine->spu_channel & 0x1f) != stream_id) {
#if LOG_SPU
printf("dxr3_decode_spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id);
#endif
return;
}
- if ((this->menu == 0) && (this->xine->spu_channel & 0x80)) {
+ if ((this->menu == 0) && (this->xine->spu_channel & 0x80)) {
#if LOG_SPU
printf("dxr3_decode_spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id);
#endif
return;
}
+ /* write sync timestamp to the card */
if (buf->pts) {
int64_t vpts;
uint32_t vpts32;
vpts = this->xine->metronom->got_spu_packet(
this->xine->metronom, buf->pts);
+ /* estimate with current time, when metronom doesn't know */
+ if (!vpts) vpts = this->xine->metronom->get_current_time(this->xine->metronom);
#if LOG_PTS
- printf ("dxr3_decode_spu: pts=%lld vpts=%lld\n", buf->pts, vpts);
+ printf("dxr3_decode_spu: pts = %lld vpts = %lld\n", buf->pts, vpts);
#endif
vpts32 = vpts;
if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32))
printf("dxr3_decode_spu: spu setpts failed (%s)\n", strerror(errno));
}
+ /* write spu data to the card */
#if LOG_SPU
printf ("dxr3_decode_spu: write: SPU_FD = %i\n",this->fd_spu);
#endif
@@ -302,6 +357,11 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
static void dxr3_spudec_reset(spu_decoder_t *this_gen)
{
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
+ int i;
+
+ for (i = 0; i < MAX_SPU_STREAMS; i++)
+ this->spu_stream_state[i].spu_length = 0;
}
static void dxr3_spudec_close(spu_decoder_t *this_gen)
@@ -344,7 +404,7 @@ static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen)
xine_spu_event_t *event = (xine_spu_event_t *)event_gen;
#if LOG_SPU
- printf ("dxr3_decode_spu: event caught: SPU_FD = %i\n",this->fd_spu);
+ printf("dxr3_decode_spu: event caught: SPU_FD = %i\n",this->fd_spu);
#endif
switch (event->event.type) {
@@ -353,16 +413,16 @@ static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen)
spu_button_t *but = event->data;
em8300_button_t btn;
#if LOG_BTN
- printf ("dxr3_decode_spu: got SPU_BUTTON\n");
+ printf("dxr3_decode_spu: got SPU_BUTTON\n");
#endif
this->buttonN = but->buttonN;
if ((but->show > 0) && (dxr3_spudec_copy_nav_to_btn(
- &this->pci, this->buttonN, but->show - 1, &btn) > 0))
+ this, but->show - 1, &btn) > 0))
if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn))
printf("dxr3_decode_spu: failed to set spu button (%s)\n",
strerror(errno));
#if LOG_BTN
- printf ("dxr3_decode_spu: buttonN = %u\n",but->buttonN);
+ printf("dxr3_decode_spu: buttonN = %u\n",but->buttonN);
#endif
}
break;
@@ -371,7 +431,7 @@ static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen)
{
spudec_clut_table_t *clut = event->data;
#if LOG_SPU
- printf ("dxr3_spu: got SPU_CLUT\n");
+ printf("dxr3_decode_spu: got SPU_CLUT\n");
#endif
#ifdef WORDS_BIGENDIAN
dxr3_swab_clut(clut->clut);
@@ -381,16 +441,25 @@ static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen)
strerror(errno));
}
break;
+#if 0
+ /* FIXME: I think this event is not necessary any more
+ * We know from nav packet decoding, if we are in a menu. */
case XINE_EVENT_SPU_FORCEDISPLAY:
{
this->menu = (int)event->data;
+#if LOG_SPU
+ printf("dxr3_decode_spu: got SPU_FORCEDISPLAY, force display is %s\n",
+ this->menu ? "on" : "off");
+#endif
}
break;
+#endif
}
}
-static int dxr3_spudec_copy_nav_to_btn(pci_t *nav_pci, int32_t button, int32_t mode, em8300_button_t *btn)
+static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300_button_t *btn)
{
+ int32_t button = this->buttonN;
btni_t *button_ptr;
/* FIXME: Need to communicate with dvdnav vm to get/set
@@ -402,19 +471,19 @@ static int dxr3_spudec_copy_nav_to_btn(pci_t *nav_pci, int32_t button, int32_t m
* }
*/
- if ((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) {
+ if ((button <= 0) || (button > this->pci.hli.hl_gi.btn_ns)) {
printf("dxr3_decode_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n",
button);
button = 1;
}
- button_ptr = &nav_pci->hli.btnit[button-1];
+ button_ptr = &this->pci.hli.btnit[button-1];
if(button_ptr->btn_coln != 0) {
#if LOG_BTN
fprintf(stderr, "dxr3_decode_spu: normal button clut, mode %d\n", mode);
#endif
- btn->color = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] >> 16);
- btn->contrast = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode]);
+ btn->color = (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] >> 16);
+ btn->contrast = (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode]);
/* FIXME: Only the first grouping of buttons are used at the moment */
btn->left = button_ptr->x_start;
btn->top = button_ptr->y_start;