summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libspudec/spu.c347
-rw-r--r--src/libspudec/spu.h38
-rw-r--r--src/libspudec/xine_decoder.c414
-rw-r--r--src/xine-engine/video_overlay.c3
4 files changed, 349 insertions, 453 deletions
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c
index 382eb7ab9..0c03d30e2 100644
--- a/src/libspudec/spu.c
+++ b/src/libspudec/spu.c
@@ -35,7 +35,7 @@
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: spu.c,v 1.30 2002/02/25 23:44:06 jcdutton Exp $
+ * $Id: spu.c,v 1.31 2002/03/25 13:57:25 jcdutton Exp $
*
*/
@@ -47,17 +47,136 @@
#include <inttypes.h>
#include <malloc.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <fcntl.h>
#include "video_out/alphablend.h"
#include "xineutils.h"
#include "xine_internal.h"
#include "spu.h"
+#include "buffer.h"
+#include "events.h"
+#include "xine-engine/bswap.h"
+#include "nav_types.h"
+#include "nav_read.h"
+#include "nav_print.h"
/*
#define LOG_DEBUG 1
*/
+/* FIXME: This function needs checking */
+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 < MAX_STREAMS; i++) {
+ this->spu_stream_state[i].stream_filter = 1; /* So it works with non-navdvd plugins */
+ this->spu_stream_state[i].ra_complete = 1;
+ this->spu_stream_state[i].overlay_handle = -1;
+ }
+}
+
+void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) {
+ uint8_t *p;
+ uint32_t packet_len;
+ uint32_t stream_id;
+ uint32_t header_len;
+ pci_t pci;
+ dsi_t dsi;
+ video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
+
+ p = buf->content;
+ if (p[0] || p[1] || (p[2] != 1)) {
+ printf("libspudec:spudec_decode_nav:nav demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
+ return;
+ }
+
+ packet_len = p[4] << 8 | p[5];
+ stream_id = p[3];
+
+ header_len = 6;
+ p += header_len;
+
+ if (stream_id == 0xbf) { /* Private stream 2 */
+/* int i;
+ * for(i=0;i<80;i++) {
+ * printf("%02x ",p[i]);
+ * }
+ * printf("\n p[0]=0x%02x\n",p[0]);
+ */
+ if(p[0] == 0x00) {
+#ifdef LOG_DEBUG
+ printf("libspudec:nav_PCI\n");
+#endif
+ nav_read_pci(&pci, p+1);
+#ifdef LOG_DEBUG
+ printf("libspudec:nav:hli_ss=%u, hli_s_ptm=%u, hli_e_ptm=%u, btn_sl_e_ptm=%u pts=%u\n",
+ pci->hli.hl_gi.hli_ss,
+ pci->hli.hl_gi.hli_s_ptm,
+ pci->hli.hl_gi.hli_e_ptm,
+ pci->hli.hl_gi.btn_se_e_ptm,
+ buf->pts);
+ printf("libspudec:nav:btn_sn/ofn=%u, btn_ns=%u, fosl_btnn=%u, foac_btnn=%u\n",
+ pci->hli.hl_gi.btn_ofn, pci->hli.hl_gi.btn_ns,
+ pci->hli.hl_gi.fosl_btnn, pci->hli.hl_gi.foac_btnn);
+ printf("btngr_ns %d\n", pci->hli.hl_gi.btngr_ns);
+ printf("btngr%d_dsp_ty 0x%02x\n", 1, pci->hli.hl_gi.btngr1_dsp_ty);
+ printf("btngr%d_dsp_ty 0x%02x\n", 2, pci->hli.hl_gi.btngr2_dsp_ty);
+ printf("btngr%d_dsp_ty 0x%02x\n", 3, pci->hli.hl_gi.btngr3_dsp_ty);
+ //navPrint_PCI(&pci);
+
+#endif
+ }
+
+ p += packet_len;
+
+ /* We should now have a DSI packet. */
+ /* We don't need anything from the DSI packet here. */
+ if(p[6] == 0x01) {
+ packet_len = p[4] << 8 | p[5];
+ p += 6;
+#ifdef LOG_DEBUG
+ printf("NAV DSI packet\n");
+#endif
+ nav_read_dsi(&dsi, p+1);
+
+// self->vobu_start = self->dsi.dsi_gi.nv_pck_lbn;
+// self->vobu_length = self->dsi.dsi_gi.vobu_ea;
+ }
+ }
+ if (pci.hli.hl_gi.hli_ss == 1) {
+ xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
+ }
+ if ( (pci.hli.hl_gi.hli_ss == 0) &&
+ (this->pci.hli.hl_gi.hli_ss == 1) ) {
+ xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
+ /* Hide menu spu between menus */
+ printf("libspudec:nav:SHOULD HIDE SPU here\n");
+ if( this->menu_handle < 0 ) {
+ this->menu_handle = ovl_instance->get_handle(ovl_instance,1);
+ }
+ if( this->menu_handle >= 0 ) {
+ metronom_t *metronom = this->xine->metronom;
+ this->event.object.handle = this->menu_handle;
+ this->event.event_type = EVENT_HIDE_SPU;
+ /* if !vpts then we are near a discontinuity but video_out havent detected
+ it yet and we cannot provide correct vpts values. use current_time
+ instead as an aproximation.
+ */
+ this->event.vpts = metronom->got_spu_packet(metronom, pci.pci_gi.vobu_s_ptm, 0);
+ ovl_instance->add_event(ovl_instance, (void *)&this->event);
+ } else {
+ printf("libspudec: No video_overlay handles left for menu\n");
+ }
+ }
+ return;
+}
+
/* Return value: reassembly complete = 1 */
int spu_reassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len)
{
@@ -71,21 +190,14 @@ int spu_reassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len)
seq->cmd_offs = (((u_int)pkt_data[2])<<8) | pkt_data[3];
if (seq->buf_len < seq->seq_len) {
- if (seq->buf) {
+ seq->buf_len = seq->seq_len;
#ifdef LOG_DEBUG
- printf ("spu: FREE1: seq->buf %p\n", seq->buf);
+ printf ("spu: MALLOC1: seq->buf %p, len=%d\n", seq->buf,seq->buf_len);
#endif
+ if (seq->buf) {
free(seq->buf);
seq->buf = NULL;
-#ifdef LOG_DEBUG
- printf ("spu: FREE2: seq->buf %p\n", seq->buf);
-#endif
}
-
- seq->buf_len = seq->seq_len;
-#ifdef LOG_DEBUG
- printf ("spu: MALLOC1: seq->buf %p, len=%d\n", seq->buf,seq->buf_len);
-#endif
seq->buf = malloc(seq->buf_len);
#ifdef LOG_DEBUG
printf ("spu: MALLOC2: seq->buf %p, len=%d\n", seq->buf,seq->buf_len);
@@ -116,12 +228,12 @@ int spu_reassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len)
return 0;
}
-int spu_next_event(spu_state_t *state, spu_seq_t* seq, int pts)
+int spu_next_event(spu_state_t *state, spu_seq_t* seq, int64_t pts)
{
uint8_t *buf = state->cmd_ptr;
if (state->next_pts == -1) { /* timestamp valid? */
- state->next_pts = seq->PTS + ((buf[0] << 8) + buf[1]) * 1024;
+ state->next_pts = seq->pts + ((buf[0] << 8) + buf[1]) * 1024;
buf += 2;
state->cmd_ptr = buf;
}
@@ -370,22 +482,20 @@ void spu_draw_picture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl)
* ovl->clip_right = ovl->width - 1;
*/
-/* spu_update_menu(state, ovl); FIXME: What is this for? */
- /* buffer is believed to be sufficiently large
- * with cmd_offs * 2 * sizeof(rle_elem_t), is that true? */
-// if (seq->cmd_offs * 2 * sizeof(rle_elem_t) > ovl->data_size) {
-// if (ovl->rle)
-// free(ovl->rle);
- ovl->data_size = seq->cmd_offs * 2 * sizeof(rle_elem_t);
+ ovl->data_size = seq->cmd_offs * 2 * sizeof(rle_elem_t);
#ifdef LOG_DEBUG
- printf ("spu: MALLOC1: ovl->rle %p, len=%d\n", ovl->rle,ovl->data_size);
+ printf ("spu: MALLOC1: ovl->rle %p, len=%d\n", ovl->rle,ovl->data_size);
#endif
- ovl->rle = malloc(ovl->data_size);
+ if (ovl->rle) {
+ printf ("libspudec: spu_draw_picture: ovl->rle is not empty!!!! It should be!!! You should never see this message.\n");
+ free(ovl->rle);
+ ovl->rle=NULL;
+ }
+ ovl->rle = malloc(ovl->data_size);
#ifdef LOG_DEBUG
- printf ("spu: MALLOC2: ovl->rle %p, len=%d\n", ovl->rle,ovl->data_size);
+ printf ("spu: MALLOC2: ovl->rle %p, len=%d\n", ovl->rle,ovl->data_size);
#endif
-// }
state->modified = 0; /* mark as already processed */
rle = ovl->rle;
@@ -551,3 +661,192 @@ void spu_update_menu (spu_state_t *state, vo_overlay_t *ovl) {
state->visible = 0;
}
}
+
+void spudec_print_overlay( vo_overlay_t *ovl ) {
+#ifdef LOG_DEBUG
+ printf ("spu: OVERLAY to show\n");
+ printf ("spu: \tx = %d y = %d width = %d height = %d\n",
+ ovl->x, ovl->y, ovl->width, ovl->height );
+ printf ("spu: \tclut [%x %x %x %x]\n",
+ ovl->color[0], ovl->color[1], ovl->color[2], ovl->color[3]);
+ printf ("spu: \ttrans [%d %d %d %d]\n",
+ ovl->trans[0], ovl->trans[1], ovl->trans[2], ovl->trans[3]);
+ printf ("spu: \tclip top=%d bottom=%d left=%d right=%d\n",
+ ovl->clip_top, ovl->clip_bottom, ovl->clip_left, ovl->clip_right);
+#endif
+ return;
+}
+void spudec_copy_nav_to_spu(spudec_decoder_t *this) {
+ int button;
+ btni_t *button_ptr;
+ int i;
+
+ button = this->buttonN;
+ /* FIXME: Need to communicate with dvdnav vm to get/set
+ "self->vm->state.HL_BTNN_REG" info.
+ now done via button events from dvdnav.
+ */
+ if ( this->pci.hli.hl_gi.fosl_btnn > 0) {
+ button = this->pci.hli.hl_gi.fosl_btnn ;
+ }
+ if((button <= 0) || (button > this->pci.hli.hl_gi.btn_ns)) {
+ printf("libspudec:xine_decoder.c:Unable to select button number %i as it doesn't exist. Forcing button 1",
+ button);
+ button = 1;
+ }
+ /* FIXME:Only the first grouping of buttons are used at the moment */
+ button_ptr = &this->pci.hli.btnit[button-1];
+ this->overlay.clip_left = button_ptr->x_start;
+ this->overlay.clip_top = button_ptr->y_start;
+ this->overlay.clip_right = button_ptr->x_end;
+ this->overlay.clip_bottom = button_ptr->y_end;
+ if(button_ptr->btn_coln != 0) {
+ for (i = 0;i < 4; i++) {
+ this->overlay.clip_color[i] = this->state.clut[0xf & (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> (16 + 4*i))];
+ this->overlay.clip_trans[i] = 0xf & (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> (4*i));
+ }
+ } else {
+ for (i = 0;i < 4; i++) {
+ printf("libspudec:btn_coln = 0, clip_color = color\n");
+ this->overlay.clip_color[i] = this->overlay.color[i];
+ this->overlay.clip_trans[i] = this->overlay.trans[i];
+ }
+ }
+/*************************
+ printf("libspudec:xine_decode.c:color3=%08x\n",this->overlay.color[3]);
+ printf("libspudec:xine_decode.c:color2=%08x\n",this->overlay.color[2]);
+ printf("libspudec:xine_decode.c:color1=%08x\n",this->overlay.color[1]);
+ printf("libspudec:xine_decode.c:color0=%08x\n",this->overlay.color[0]);
+ printf("libspudec:xine_decode.c:trans3=%08x\n",this->overlay.trans[3]);
+ printf("libspudec:xine_decode.c:trans2=%08x\n",this->overlay.trans[2]);
+ printf("libspudec:xine_decode.c:trans1=%08x\n",this->overlay.trans[1]);
+ printf("libspudec:xine_decode.c:trans0=%08x\n",this->overlay.trans[0]);
+*************************/
+
+ printf("libspudec:xine_decoder.c:NAV to SPU pts match!\n");
+
+}
+
+void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
+ spu_seq_t *cur_seq;
+ video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
+ int pending = 1;
+ cur_seq = &this->spu_stream_state[stream_id].ra_seq;
+
+/* FIXME:Get Handle after we have found if "Forced display" is set or not.
+ */
+
+#ifdef LOG_DEBUG
+ printf ("spu: Found SPU from stream %d pts=%d vpts=%d\n",stream_id,
+ this->spu_stream_state[stream_id].pts,
+ this->spu_stream_state[stream_id].vpts);
+#endif
+ this->state.cmd_ptr = cur_seq->buf + cur_seq->cmd_offs;
+ this->state.next_pts = -1; /* invalidate timestamp */
+ this->state.modified = 1; /* Only draw picture if = 1 on first event of SPU */
+ this->state.visible = 0; /* 0 - No value, 1 - Show, 2 - Hide. */
+ this->state.menu = 0; /* 0 - No value, 1 - Forced Display. */
+ this->state.delay = 0;
+ cur_seq->finished=0;
+
+ do {
+ if (!(cur_seq->finished) ) {
+
+ /* Get do commands to build the event. */
+ spu_do_commands(&this->state, cur_seq, &this->overlay);
+ /* FIXME: Check for Forced-display or subtitle stream
+ * For subtitles, open event.
+ * For menus, store it for later.
+ */
+ /* spu_channel is now set based on whether we are in the menu or not. */
+ /* Bit 7 is set if only forced display SPUs should be shown */
+ if ( (this->xine->spu_channel & 0x1f) != stream_id ) {
+#ifdef LOG_DEBUG
+ printf ("spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id);
+#endif
+ return;
+ }
+ if ( (this->state.menu == 0) && (this->xine->spu_channel & 0x80) ) {
+#ifdef LOG_DEBUG
+ printf ("spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id);
+#endif
+ return;
+ }
+
+#ifdef LOG_DEBUG
+ /* spudec_print_overlay( &this->overlay ); */
+ printf ("spu: forced display:%s\n", this->state.menu ? "Yes" : "No" );
+#endif
+ if (this->pci.hli.hl_gi.hli_s_ptm == this->spu_stream_state[stream_id].pts) {
+ spudec_copy_nav_to_spu(this);
+ } else {
+ /* Subtitle and not a menu button */
+ int i;
+ for (i = 0;i < 4; i++) {
+ this->overlay.clip_color[i] = this->overlay.color[i];
+ this->overlay.clip_trans[i] = this->overlay.trans[i];
+ }
+ }
+
+ if ( !(this->overlay.trans[0] | this->overlay.trans[1] | this->overlay.trans[2] | this->overlay.trans[3] |
+ this->overlay.clip_trans[0] | this->overlay.clip_trans[1] | this->overlay.clip_trans[2] | this->overlay.clip_trans[3]) ) {
+ /* SPU is transparent so why bother displaying it. */
+ printf ("spu: transparent spu found, discarding it.\n" );
+ return;
+ }
+
+ if ((this->state.modified) ) {
+ spu_draw_picture(&this->state, cur_seq, &this->overlay);
+ }
+
+ if (this->state.need_clut) {
+ spu_discover_clut(&this->state, &this->overlay);
+ }
+
+ /* Subtitle */
+ if( this->menu_handle < 0 ) {
+ this->menu_handle = ovl_instance->get_handle(ovl_instance,1);
+ }
+
+ if( this->menu_handle < 0 ) {
+ printf("libspudec: No video_overlay handles left for menu\n");
+ return;
+ }
+ this->event.object.handle = this->menu_handle;
+ this->event.object.pts = this->spu_stream_state[stream_id].pts;
+
+ xine_fast_memcpy(this->event.object.overlay,
+ &this->overlay,
+ sizeof(vo_overlay_t));
+ this->overlay.rle=NULL;
+ /* For force display menus */
+ if ( !(this->state.visible) ) {
+ this->state.visible = EVENT_SHOW_SPU;
+ }
+
+ this->event.event_type = this->state.visible;
+ /*
+ printf("spu event %d handle: %d vpts: %d\n", this->event.event_type,
+ this->event.object.handle, this->event.vpts );
+ */
+
+ /* if !vpts then we are near a discontinuity but video_out havent detected
+ it yet and we cannot provide correct vpts values. use current_time
+ instead as an aproximation.
+ */
+ if( this->spu_stream_state[stream_id].vpts ) {
+ this->event.vpts = this->spu_stream_state[stream_id].vpts+(this->state.delay*1000);
+ } else {
+ this->event.vpts = this->xine->metronom->get_current_time(this->xine->metronom)
+ + (this->state.delay*1000);
+ printf("libspudec: vpts current time estimation around discontinuity\n");
+ }
+ ovl_instance->add_event(ovl_instance, (void *)&this->event);
+ } else {
+ pending = 0;
+ }
+ } while (pending);
+
+}
+
+
diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h
index 8b62301e3..695deb8a1 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.9 2002/01/06 18:27:47 jcdutton Exp $
+ * $Id: spu.h,v 1.10 2002/03/25 13:57:25 jcdutton Exp $
*
* This file was originally part of the OMS program.
*
@@ -62,7 +62,7 @@ typedef struct {
u_int cmd_offs;
- u_int PTS; /* Base PTS of this sequence */
+ int64_t pts; /* Base PTS of this sequence */
int finished; /* Has this sequence been finished? */
} spu_seq_t;
@@ -75,7 +75,7 @@ typedef struct {
int b_left, o_left;
int b_right, o_right;
- u_int next_pts; /* pts of next sub-sequence */
+ int64_t 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 */
@@ -87,21 +87,13 @@ typedef struct {
uint32_t clut[16];
} spu_state_t;
-int spu_reassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len);
-int spu_next_event (spu_state_t *state, spu_seq_t* seq, int pts);
-void spu_do_commands (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
-void spu_draw_picture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
-void spu_discover_clut (spu_state_t *state, vo_overlay_t *ovl);
-void spu_update_menu (spu_state_t *state, vo_overlay_t *ovl);
-
-
typedef struct spudec_stream_state_s {
spu_seq_t ra_seq;
uint32_t ra_complete;
uint32_t stream_filter;
spu_state_t state;
- uint32_t vpts;
- uint32_t pts;
+ int64_t vpts;
+ int64_t pts;
int32_t overlay_handle;
} spudec_stream_state_t;
@@ -109,19 +101,14 @@ typedef struct spudec_decoder_s {
spu_decoder_t spu_decoder;
xine_t *xine;
-/* spu_seq_t seq_list[NUM_SEQ_BUFFERS]; */
- spu_seq_t *cur_seq;
spudec_stream_state_t spu_stream_state[MAX_STREAMS];
video_overlay_event_t event;
video_overlay_object_t object;
int32_t menu_handle;
- spu_seq_t *ra_seq;
- int ra_complete;
-
- uint32_t ovl_pts;
- uint32_t buf_pts;
+ int64_t ovl_pts;
+ int64_t buf_pts;
spu_state_t state;
vo_instance_t *vo_out;
@@ -132,5 +119,16 @@ typedef struct spudec_decoder_s {
uint32_t buttonN; /* Current button number for highlights */
} spudec_decoder_t;
+int spu_reassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len);
+int spu_next_event (spu_state_t *state, spu_seq_t* seq, int64_t pts);
+void spu_do_commands (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
+void spu_draw_picture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
+void spu_discover_clut (spu_state_t *state, vo_overlay_t *ovl);
+void spu_update_menu (spu_state_t *state, vo_overlay_t *ovl);
+void spudec_reset (spudec_decoder_t *this);
+void spudec_print_overlay( vo_overlay_t *overlay );
+void spudec_copy_nav_to_spu( spudec_decoder_t *this );
+void spu_process( spudec_decoder_t *this, uint32_t stream_id);
+void spudec_decode_nav( spudec_decoder_t *this, buf_element_t *buf);
#endif
diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c
index 98f8947b5..64cdff773 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.57 2002/03/11 12:31:26 guenter Exp $
+ * $Id: xine_decoder.c,v 1.58 2002/03/25 13:57:25 jcdutton Exp $
*
* stuff needed to turn libspu into a xine decoder plugin
*/
@@ -71,31 +71,6 @@ static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT || type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL) ;
}
-/* FIXME: This function needs checking */
-static void spudec_reset (spudec_decoder_t *this) {
- int i;
-
- this->ovl_pts = 0;
- this->buf_pts = 0;
-
- this->state.visible = 0;
-
-// this->seq_list[0].finished = 1; /* mark as cur_seq */
-// for (i = 1; i < NUM_SEQ_BUFFERS; i++) {
-// this->seq_list[i].finished = 2; /* free for reassembly */
-// }
- for (i=0; i < MAX_STREAMS; i++) {
- this->spu_stream_state[i].stream_filter = 1; /* So it works with non-navdvd plugins */
- this->spu_stream_state[i].ra_complete = 1;
- this->spu_stream_state[i].overlay_handle = -1;
- }
-
-/* I don't think I need this.
- this->cur_seq = this->ra_seq = this->seq_list;
- */
-}
-
-
static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
@@ -110,339 +85,6 @@ static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
this->state.need_clut = 1;
}
-static void spudec_print_overlay( vo_overlay_t *ovl ) {
-#ifdef LOG_DEBUG
- printf ("spu: OVERLAY to show\n");
- printf ("spu: \tx = %d y = %d width = %d height = %d\n",
- ovl->x, ovl->y, ovl->width, ovl->height );
- printf ("spu: \tclut [%x %x %x %x]\n",
- ovl->color[0], ovl->color[1], ovl->color[2], ovl->color[3]);
- printf ("spu: \ttrans [%d %d %d %d]\n",
- ovl->trans[0], ovl->trans[1], ovl->trans[2], ovl->trans[3]);
- printf ("spu: \tclip top=%d bottom=%d left=%d right=%d\n",
- ovl->clip_top, ovl->clip_bottom, ovl->clip_left, ovl->clip_right);
-#endif
- return;
-}
-static void spudec_copy_nav_to_spu(spudec_decoder_t *this) {
- int button;
- btni_t *button_ptr;
- int i;
-
- button = this->buttonN;
- /* FIXME: Need to communicate with dvdnav vm to get/set
- "self->vm->state.HL_BTNN_REG" info.
- now done via button events from dvdnav.
- */
- if ( this->pci.hli.hl_gi.fosl_btnn > 0) {
- button = this->pci.hli.hl_gi.fosl_btnn ;
- }
- if((button <= 0) || (button > this->pci.hli.hl_gi.btn_ns)) {
- printf("libspudec:xine_decoder.c:Unable to select button number %i as it doesn't exist. Forcing button 1",
- button);
- button = 1;
- }
- /* FIXME:Only the first grouping of buttons are used at the moment */
- button_ptr = &this->pci.hli.btnit[button-1];
- this->overlay.clip_left = button_ptr->x_start;
- this->overlay.clip_top = button_ptr->y_start;
- this->overlay.clip_right = button_ptr->x_end;
- this->overlay.clip_bottom = button_ptr->y_end;
- if(button_ptr->btn_coln != 0) {
- for (i = 0;i < 4; i++) {
- this->overlay.clip_color[i] = this->state.clut[0xf & (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> (16 + 4*i))];
- this->overlay.clip_trans[i] = 0xf & (this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> (4*i));
- }
- } else {
- for (i = 0;i < 4; i++) {
- printf("libspudec:btn_coln = 0, clip_color = color\n");
- this->overlay.clip_color[i] = this->overlay.color[i];
- this->overlay.clip_trans[i] = this->overlay.trans[i];
- }
- }
-/*************************
- printf("libspudec:xine_decode.c:color3=%08x\n",this->overlay.color[3]);
- printf("libspudec:xine_decode.c:color2=%08x\n",this->overlay.color[2]);
- printf("libspudec:xine_decode.c:color1=%08x\n",this->overlay.color[1]);
- printf("libspudec:xine_decode.c:color0=%08x\n",this->overlay.color[0]);
- printf("libspudec:xine_decode.c:trans3=%08x\n",this->overlay.trans[3]);
- printf("libspudec:xine_decode.c:trans2=%08x\n",this->overlay.trans[2]);
- printf("libspudec:xine_decode.c:trans1=%08x\n",this->overlay.trans[1]);
- printf("libspudec:xine_decode.c:trans0=%08x\n",this->overlay.trans[0]);
-*************************/
-
- printf("libspudec:xine_decoder.c:NAV to SPU pts match!\n");
-
-}
-
-static void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
-// spu_overlay_event_t *event;
-// spu_object_t *object;
-// vo_overlay_t *overlay;
- video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
- int pending = 1;
- this->cur_seq = &this->spu_stream_state[stream_id].ra_seq;
-
-/* FIXME:Get Handle after we have found if "Forced display" is set or not.
- */
-
-#ifdef LOG_DEBUG
- printf ("spu: Found SPU from stream %d pts=%d vpts=%d\n",stream_id,
- this->spu_stream_state[stream_id].pts,
- this->spu_stream_state[stream_id].vpts);
-#endif
- this->state.cmd_ptr = this->cur_seq->buf + this->cur_seq->cmd_offs;
- this->state.next_pts = -1; /* invalidate timestamp */
- this->state.modified = 1; /* Only draw picture if = 1 on first event of SPU */
- this->state.visible = 0; /* 0 - No value, 1 - Show, 2 - Hide. */
- this->state.menu = 0; /* 0 - No value, 1 - Forced Display. */
- this->state.delay = 0;
- this->cur_seq->finished=0;
-
- do {
- if (!this->spu_stream_state[stream_id].ra_seq.finished) {
-
- //spudec_nextseq(this);
-/* Get do commands to build the event. */
- spu_do_commands(&this->state, this->cur_seq, &this->overlay);
- /* FIXME: Check for Forced-display or subtitle stream
- * For subtitles, open event.
- * For menus, store it for later.
- */
-/* spu_channel is now set based on whether we are in the menu or not. */
-/* Bit 7 is set if only forced display SPUs should be shown */
- if ( (this->xine->spu_channel & 0x1f) != stream_id ) {
-#ifdef LOG_DEBUG
- printf ("spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id);
-#endif
- return;
- }
- if ( (this->state.menu == 0) && (this->xine->spu_channel & 0x80) ) {
-#ifdef LOG_DEBUG
- printf ("spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id);
-#endif
- return;
- }
-
-#ifdef LOG_DEBUG
- /* spudec_print_overlay( &this->overlay ); */
- printf ("spu: forced display:%s\n", this->state.menu ? "Yes" : "No" );
-#endif
- if (this->pci.hli.hl_gi.hli_s_ptm == this->spu_stream_state[stream_id].pts) {
- spudec_copy_nav_to_spu(this);
- } else {
- /* Subtitle and not a menu button */
- int i;
- for (i = 0;i < 4; i++) {
- this->overlay.clip_color[i] = this->overlay.color[i];
- this->overlay.clip_trans[i] = this->overlay.trans[i];
- }
- }
-
- if ( !(this->overlay.trans[0] | this->overlay.trans[1] | this->overlay.trans[2] | this->overlay.trans[3] |
- this->overlay.clip_trans[0] | this->overlay.clip_trans[1] | this->overlay.clip_trans[2] | this->overlay.clip_trans[3]) ) {
- /* SPU is transparent so why bother displaying it. */
- printf ("spu: transparent spu found, discarding it.\n" );
- return;
- }
-
- if ((this->state.modified) ) {
- spu_draw_picture(&this->state, this->cur_seq, &this->overlay);
- }
-
- if (this->state.need_clut)
- spu_discover_clut(&this->state, &this->overlay);
-
- //if (this->state.menu == 0) {
- if (1) {
- /* Subtitle */
- if( this->menu_handle < 0 ) {
- this->menu_handle = ovl_instance->get_handle(ovl_instance,1);
- }
-
- if( this->menu_handle < 0 ) {
- printf("libspudec: No video_overlay handles left for menu\n");
- return;
- }
- this->event.object.handle = this->menu_handle;
- this->event.object.pts = this->spu_stream_state[stream_id].pts;
-
-/*******************************
- if( this->spu_stream_state[stream_id].overlay_handle < 0 ) {
- this->spu_stream_state[stream_id].overlay_handle =
- this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source, 0);
- }
-
- if( this->spu_stream_state[stream_id].overlay_handle < 0 ) {
- printf("libspudec: No video_overlay handles left for SPU\n");
- return;
- }
-
- this->event.object.handle = this->spu_stream_state[stream_id].overlay_handle;
-*********************************/
-
- xine_fast_memcpy(this->event.object.overlay,
- &this->overlay,
- sizeof(vo_overlay_t));
- this->overlay.rle=NULL;
- /* For force display menus */
- if ( !(this->state.visible) ) {
- this->state.visible = EVENT_SHOW_SPU;
- }
-
- this->event.event_type = this->state.visible;
- /* event hide event must free the handle after use */
-/******************************
- if( this->event.event_type == EVENT_HIDE_SPU ) {
- this->spu_stream_state[stream_id].overlay_handle = -1;
- }
-*******************************/
- /*
- printf("spu event %d handle: %d vpts: %d\n", this->event.event_type,
- this->event.object.handle, this->event.vpts );
- */
- } else {
- /* Menu */
- if( this->menu_handle < 0 ) {
- this->menu_handle = ovl_instance->get_handle (ovl_instance, 1);
- }
-
- if( this->menu_handle < 0 ) {
- printf("libspudec: No video_overlay handles left for menu\n");
- return;
- }
- this->event.object.handle = this->menu_handle;
-
- xine_fast_memcpy(this->event.object.overlay,
- &this->overlay,
- sizeof(vo_overlay_t));
- this->overlay.rle=NULL;
-
- this->event.event_type = EVENT_MENU_SPU;
- //this->event.event_type = EVENT_SHOW_SPU;
- }
-
- /* if !vpts then we are near a discontinuity but video_out havent detected
- it yet and we cannot provide correct vpts values. use current_time
- instead as an aproximation.
- */
- if( this->spu_stream_state[stream_id].vpts ) {
- this->event.vpts = this->spu_stream_state[stream_id].vpts+(this->state.delay*1000);
- } else {
- this->event.vpts = this->xine->metronom->get_current_time(this->xine->metronom)
- + (this->state.delay*1000);
- printf("libspudec: vpts current time estimation around discontinuity\n");
- }
- ovl_instance->add_event(ovl_instance, (void *)&this->event);
- } else {
- pending = 0;
- }
- } while (pending);
-
-}
-
-static void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) {
- uint8_t *p;
- uint32_t packet_len;
- uint32_t stream_id;
- uint32_t header_len;
- pci_t *pci;
- dsi_t *dsi;
- video_overlay_instance_t *ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
-
- p = buf->content;
- if (p[0] || p[1] || (p[2] != 1)) {
- printf("libspudec:spudec_decode_nav:nav demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
- return;
- }
- pci=xine_xmalloc(sizeof(pci_t));
- dsi=xine_xmalloc(sizeof(dsi_t));
-
- packet_len = p[4] << 8 | p[5];
- stream_id = p[3];
-
- header_len = 6;
- p += header_len;
-
- if (stream_id == 0xbf) { /* Private stream 2 */
-/* int i;
- * for(i=0;i<80;i++) {
- * printf("%02x ",p[i]);
- * }
- * printf("\n p[0]=0x%02x\n",p[0]);
- */
- if(p[0] == 0x00) {
-#ifdef LOG_DEBUG
- printf("libspudec:nav_PCI\n");
-#endif
- nav_read_pci(pci, p+1);
-#ifdef LOG_DEBUG
- printf("libspudec:nav:hli_ss=%u, hli_s_ptm=%u, hli_e_ptm=%u, btn_sl_e_ptm=%u pts=%u\n",
- pci->hli.hl_gi.hli_ss,
- pci->hli.hl_gi.hli_s_ptm,
- pci->hli.hl_gi.hli_e_ptm,
- pci->hli.hl_gi.btn_se_e_ptm,
- buf->PTS);
- printf("libspudec:nav:btn_sn/ofn=%u, btn_ns=%u, fosl_btnn=%u, foac_btnn=%u\n",
- pci->hli.hl_gi.btn_ofn, pci->hli.hl_gi.btn_ns,
- pci->hli.hl_gi.fosl_btnn, pci->hli.hl_gi.foac_btnn);
- printf("btngr_ns %d\n", pci->hli.hl_gi.btngr_ns);
- printf("btngr%d_dsp_ty 0x%02x\n", 1, pci->hli.hl_gi.btngr1_dsp_ty);
- printf("btngr%d_dsp_ty 0x%02x\n", 2, pci->hli.hl_gi.btngr2_dsp_ty);
- printf("btngr%d_dsp_ty 0x%02x\n", 3, pci->hli.hl_gi.btngr3_dsp_ty);
- //navPrint_PCI(pci);
-
-#endif
- }
-
- p += packet_len;
-
- /* We should now have a DSI packet. */
- /* We don't need anything from the DSI packet here. */
- if(p[6] == 0x01) {
- packet_len = p[4] << 8 | p[5];
- p += 6;
-#ifdef LOG_DEBUG
- printf("NAV DSI packet\n");
-#endif
- nav_read_dsi(dsi, p+1);
-
-// self->vobu_start = self->dsi.dsi_gi.nv_pck_lbn;
-// self->vobu_length = self->dsi.dsi_gi.vobu_ea;
- }
- }
- if (pci->hli.hl_gi.hli_ss == 1) {
- xine_fast_memcpy(&this->pci, pci, sizeof(pci_t));
- }
- if ( (pci->hli.hl_gi.hli_ss == 0) &&
- (this->pci.hli.hl_gi.hli_ss == 1) ) {
- xine_fast_memcpy(&this->pci, pci, sizeof(pci_t));
- /* Hide menu spu between menus */
- printf("libspudec:nav:SHOULD HIDE SPU here\n");
- if( this->menu_handle < 0 ) {
- this->menu_handle = ovl_instance->get_handle(ovl_instance,1);
- }
- if( this->menu_handle >= 0 ) {
- metronom_t *metronom = this->xine->metronom;
- this->event.object.handle = this->menu_handle;
- this->event.event_type = EVENT_HIDE_SPU;
- /* if !vpts then we are near a discontinuity but video_out havent detected
- it yet and we cannot provide correct vpts values. use current_time
- instead as an aproximation.
- */
- this->event.vpts = metronom->got_spu_packet(metronom, pci->pci_gi.vobu_s_ptm, 0);
- ovl_instance->add_event(ovl_instance, (void *)&this->event);
- } else {
- printf("libspudec: No video_overlay handles left for menu\n");
- }
- }
- free(pci);
- free(dsi);
- return;
-}
-
-
-
static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
uint32_t stream_id;
spu_seq_t *cur_seq;
@@ -489,44 +131,18 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
if (buf->pts) {
metronom_t *metronom = this->xine->metronom;
- uint32_t vpts = metronom->got_spu_packet(metronom, buf->pts, 0);
+ int64_t vpts = metronom->got_spu_packet(metronom, buf->pts, 0);
- if (vpts < this->buf_pts) {
- /* FIXME: Don't do this yet,
- because it will cause all sorts of
- problems with malloc.
- */
- /* spudec_reset(this); */
- }
-
this->spu_stream_state[stream_id].vpts = vpts; /* Show timer */
this->spu_stream_state[stream_id].pts = buf->pts; /* Required to match up with NAV packets */
}
-/* 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 > 1) {
- this->ra_seq = tmp_seq;
- this->ra_seq->PTS = this->buf_pts;
- }
- }
- */
- stream_id = buf->type & 0x1f ;
this->spu_stream_state[stream_id].ra_complete =
spu_reassembly(&this->spu_stream_state[stream_id].ra_seq,
this->spu_stream_state[stream_id].ra_complete,
buf->content,
buf->size);
if(this->spu_stream_state[stream_id].ra_complete == 1) {
- /*
- * Testing menus
- * if(stream_id == 0) {
- * spu_process(this,stream_id);
- * }
- * End testing menus
- */
spu_process(this,stream_id);
}
}
@@ -550,24 +166,6 @@ static void spudec_close (spu_decoder_t *this_gen) {
}
}
-/* This function is probably not needed now */
-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->finished = 2; /* ready for reassembly */
- 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 void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
xine_spu_event_t *event = (xine_spu_event_t *) event_gen;
@@ -577,9 +175,6 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
return;
}
- if (this->vo_out)
- ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
-
switch (event->event.type) {
case XINE_EVENT_SPU_BUTTON:
{
@@ -659,7 +254,10 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
overlay_event->event_type = EVENT_HIDE_MENU;
}
overlay_event->vpts = 0; /* Activate it NOW */
- ovl_instance->add_event (ovl_instance, (void *)overlay_event);
+ if (this->vo_out) {
+ ovl_instance = this->vo_out->get_overlay_instance (this->vo_out);
+ ovl_instance->add_event (ovl_instance, (void *)overlay_event);
+ }
}
break;
case XINE_EVENT_SPU_CLUT:
diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c
index 2101cc455..9efc010be 100644
--- a/src/xine-engine/video_overlay.c
+++ b/src/xine-engine/video_overlay.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_overlay.c,v 1.17 2002/03/21 16:21:03 miguelfreitas Exp $
+ * $Id: video_overlay.c,v 1.18 2002/03/25 13:57:25 jcdutton Exp $
*
*/
@@ -445,6 +445,7 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) {
/* If rle is not empty, free it first */
if(overlay->rle) {
free (overlay->rle);
+ overlay->rle=NULL;
}
#ifdef LOG_DEBUG
printf("video_overlay.c:Menu SPU area is (%u,%u)-(%u,%u), display = 1\n",