diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libspudec/spu.c | 347 | ||||
-rw-r--r-- | src/libspudec/spu.h | 38 | ||||
-rw-r--r-- | src/libspudec/xine_decoder.c | 414 | ||||
-rw-r--r-- | src/xine-engine/video_overlay.c | 3 |
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", |