diff options
-rw-r--r-- | src/dxr3/Makefile.am | 9 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_spu.c | 531 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_video.c (renamed from src/dxr3/dxr3_decoder.c) | 465 |
3 files changed, 559 insertions, 446 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index 084ed26e1..5d64ac54b 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -5,7 +5,7 @@ LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic libdir = $(XINE_PLUGINDIR) if HAVE_DXR3 -dxr3_modules = xineplug_decode_dxr3.la xineplug_vo_out_dxr3.la +dxr3_modules = xineplug_decode_dxr3_video.la xineplug_decode_dxr3_spu.la xineplug_vo_out_dxr3.la endif if HAVE_LIBFAME link_fame = -lfame @@ -16,8 +16,11 @@ endif lib_LTLIBRARIES = $(dxr3_modules) -xineplug_decode_dxr3_la_SOURCES = dxr3_decoder.c nav_read.c -xineplug_decode_dxr3_la_LDFLAGS = -avoid-version -module +xineplug_decode_dxr3_video_la_SOURCES = dxr3_decode_video.c +xineplug_decode_dxr3_video_la_LDFLAGS = -avoid-version -module + +xineplug_decode_dxr3_spu_la_SOURCES = dxr3_decode_spu.c nav_read.c +xineplug_decode_dxr3_spu_la_LDFLAGS = -avoid-version -module xineplug_vo_out_dxr3_la_SOURCES = dxr3_video_out.c \ dxr3_vo_core.c mpeg_encoders.c alphablend.c diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c new file mode 100644 index 000000000..1bc0e6da3 --- /dev/null +++ b/src/dxr3/dxr3_decode_spu.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: dxr3_decode_spu.c,v 1.1 2002/05/02 14:33:30 jcdutton Exp $ + * + * dxr3 video and spu decoder plugin. Accepts the video and spu data + * from XINE and sends it directly to the corresponding dxr3 devices. + * Takes precedence over the libmpeg2 and libspudec due to a higher + * priority. + * also incorporates an scr plugin for metronom + * + * update 7/1/2002 by jcdutton: + * Updated to work better with the changes done to dvdnav. + * Subtitles display properly now. + * TODO: Process NAV packets so that the first + * menu button appears, and also so that + * menu buttons disappear when one starts playing the movie. + * Processing NAV packets will also make "The White Rabbit" + * work on DXR3 as I currently works on XV. + * + * update 25/11/01 by Harm: + * Major retooling; so much so that I've decided to cvs-tag the dxr3 sources + * as DXR3_095 before commiting. + * - major retooling of dxr3_decode_data; Mike Lampard's comments indicate + * that dxr3_decode_data is called once every 12 frames or so. This seems + * no longer true; we're in fact called on average more than once per frame. + * This gives us some interesting possibilities to lead metronom up the garden + * path (and administer it a healthy beating behind the toolshed ;-). + * Read the comments for details, but the short version is that we take a + * look at the scr clock to guestimate when we should call get_frame/draw/free. + * - renamed update_aspect to parse_mpeg_header. + * - replaced printing to stderr by stdout, following xine practice and + * to make it easier to write messages to a log. + * - replaced 6667 flag with proper define in dxr3_video_out.h + * + * The upshot of all this is that sync is a lot better now; I get good + * a/v sync within a few seconds of playing after start/seek. I also + * get a lot of "throwing away frame..." messages, especially just + * after start/seek, but those are relatively harmless. (I guess we + * call img->draw a tad too often). + * + * update 21/12/01 by Harm + * many revisions, but I've been too lazy to document them here. + * read the cvs log, that's what it's for anyways. + */ + + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> + +#include <linux/soundcard.h> +#include <linux/em8300.h> +#include "video_out.h" +#include "xine_internal.h" +#include "buffer.h" +#include "xine-engine/bswap.h" +#include "nav_types.h" +#include "nav_read.h" + +/* for DXR3_VO_UPDATE_FLAG */ +#include "dxr3_video_out.h" + +#define LOOKUP_DEV "dxr3.devicename" +#define DEFAULT_DEV "/dev/em8300" +static char devname[128]; +static char devnum[3]; + +/* lots of poohaa about pts things */ +#define LOG_PTS 0 +#define LOG_SPU 0 + +#define MV_COMMAND 0 + +/* the number of frames to pass after an out-of-sync situation + before locking the stream again */ +#define RESYNC_WINDOW_SIZE 50 + +int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn ); + +/* + * Second part of the dxr3 plugin: subpicture decoder + */ +#define MAX_SPU_STREAMS 32 + +typedef struct spudec_stream_state_s { + uint32_t stream_filter; +} spudec_stream_state_t; + +typedef struct spudec_decoder_s { + spu_decoder_t spu_decoder; + spudec_stream_state_t spu_stream_state[MAX_SPU_STREAMS]; + vo_instance_t *vo_out; + int fd_spu; + int menu; /* are we in a menu? */ + pci_t pci; + uint32_t buttonN; /* currently highlighted button */ + int64_t button_vpts; /* time to show the menu enter button */ + xine_t *xine; +} spudec_decoder_t; + +static int dxr3_presence_test( xine_t* xine) +{ + int info; + if (xine && xine->video_driver ) { + info = xine->video_driver->get_property( xine->video_driver, VO_PROP_VO_TYPE); + printf("dxr3_presence_test:info=%d\n",info); + if (info != VO_TYPE_DXR3) { + return 0; + } + } + return 1; +} + +static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) +{ + int type = buf_type & 0xFFFF0000; + return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT || + type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL); +} + +static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) +{ + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + char tmpstr[100]; + int i; + + this->vo_out = vo_out; + + /* open spu device */ + snprintf (tmpstr, sizeof(tmpstr), "%s_sp%s", devname, devnum); + if ((this->fd_spu = open (tmpstr, O_WRONLY)) < 0) { + printf("dxr3: Failed to open spu device %s (%s)\n", + tmpstr, strerror(errno)); + return; + } +#if LOG_SPU + printf ("dxr3_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 */ + this->spu_stream_state[i].stream_filter = 1; +} + +static void swab_clut(int* clut) +{ + int i; + for (i=0; i<16; i++) + clut[i] = bswap_32(clut[i]); +} + +static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) +{ + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + ssize_t written; + uint32_t stream_id = buf->type & 0x1f ; + + if (this->button_vpts && + this->xine->metronom->get_current_time(this->xine->metronom) > this->button_vpts) { + /* we have a scheduled menu enter button and it's time to show it now */ + em8300_button_t button; + int buttonNr; + btni_t *button_ptr; + + buttonNr = this->buttonN; + + if (this->pci.hli.hl_gi.fosl_btnn > 0) + buttonNr = this->pci.hli.hl_gi.fosl_btnn ; + + if ((buttonNr <= 0) || (buttonNr > this->pci.hli.hl_gi.btn_ns)) { + printf("dxr3_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n", buttonNr); + buttonNr = 1; + } + + button_ptr = &this->pci.hli.btnit[buttonNr-1]; + button.left = button_ptr->x_start; + button.top = button_ptr->y_start; + button.right = button_ptr->x_end; + button.bottom = button_ptr->y_end; + button.color = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> 16; + button.contrast = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] & 0xffff; + +#if LOG_SPU + printf("dxr3_spu: now showing menu enter button %i.\n", buttonNr); +#endif + ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &button); + this->button_vpts = 0; + this->pci.hli.hl_gi.hli_s_ptm = 0; + } + + if (buf->type == BUF_SPU_CLUT) { +#if LOG_SPU + printf ("dxr3_spu: BUF_SPU_CLUT\n" ); +#endif +#if LOG_SPU + printf ("dxr3_spu: buf clut: SPU_FD = %i\n",this->fd_spu); +#endif + if (buf->content[0] == 0) /* cheap endianess detection */ + swab_clut((int*)buf->content); + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, buf->content)) + printf("dxr3: failed to set CLUT (%s)\n", strerror(errno)); + return; + } + if(buf->type == BUF_SPU_SUBP_CONTROL){ +/*************** + int i; + uint32_t *subp_control = (uint32_t*) buf->content; + for (i = 0; i < 32; i++) { + this->spu_stream_state[i].stream_filter = subp_control[i]; + } +***************/ + return; + } + if(buf->type == BUF_SPU_NAV){ +#if LOG_SPU + printf("dxr3_spu: Got NAV packet\n"); +#endif + uint8_t *p = buf->content; + + /* just watch out for menus */ + if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */ + pci_t pci; + + nav_read_pci(&pci, p + 7); + + if (pci.hli.hl_gi.hli_ss == 1) { + em8300_button_t btn; + /* menu ahead, remember pci for later evaluation */ + xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t)); + if ( (spudec_copy_nav_to_btn(&this->pci, this->buttonN, 0, &btn ) > 0)) { + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) { + printf("dxr3: failed to set spu button (%s)\n", + strerror(errno)); + } + } + } + + if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) { + /* leaving menu */ + xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t)); + ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); + } + } + return; + } + /* Is this also needed for subpicture? */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { +#if LOG_SPU + printf ("dxr3_spu: Dropping SPU channel %d. Preview data\n", stream_id); +#endif + return; + } + + if ( this->spu_stream_state[stream_id].stream_filter == 0) { +#if LOG_SPU + printf ("dxr3_spu: Dropping SPU channel %d. Stream filtered\n", stream_id); +#endif + return; + } +/* 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 ) { +#if LOG_SPU + printf ("dxr3_spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id); +#endif + return; + } + if ( (this->menu == 0) && (this->xine->spu_channel & 0x80) ) { +#if LOG_SPU + printf ("dxr3_spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id); +#endif + return; + } +// if (this->xine->spu_channel != stream_id && this->menu!=1 ) return; + /* Hide any previous button highlights */ +// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); + if (buf->pts) { + int64_t vpts; + uint32_t vpts32; + + vpts = this->xine->metronom->got_spu_packet + (this->xine->metronom, buf->pts); +#if LOG_SPU + printf ("dxr3_spu: pts=%lld vpts=%lld\n", buf->pts, vpts); +#endif + vpts32 = vpts; + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32)) + printf("dxr3: spu setpts failed (%s)\n", strerror(errno)); + + if (buf->pts == this->pci.hli.hl_gi.hli_s_ptm) + /* schedule the menu enter button for current packet's vpts, so + that the card has decoded this SPU when we try to show the button */ + this->button_vpts = vpts; + } + + +#if LOG_SPU + printf ("dxr3_spu: write: SPU_FD = %i\n",this->fd_spu); +#endif + written = write(this->fd_spu, buf->content, buf->size); + if (written < 0) { + printf("dxr3: spu device write failed (%s)\n", + strerror(errno)); + return; + } + if (written != buf->size) + printf("dxr3: Could only write %d of %d spu bytes.\n", + written, buf->size); +} + +static void spudec_reset (spu_decoder_t *this_gen) +{ +} + +static void spudec_close (spu_decoder_t *this_gen) +{ + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; +#if LOG_SPU + printf ("dxr3_spu: close: SPU_FD = %i\n",this->fd_spu); +#endif + + close(this->fd_spu); + this->fd_spu = 0; +} + +int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn ) { + btni_t *button_ptr; + + /* 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 > nav_pci->hli.hl_gi.btn_ns)) { + printf("dxr3_decoder:Unable to select button number %i as it doesn't exist. Forcing button 1\n", + button); + button = 1; + } + /* There is no point in highlighting an area it the area's colours are no different from the general overlay colours. */ + button_ptr = &nav_pci->hli.btnit[button-1]; + if(button_ptr->btn_coln != 0) { +#ifdef LOG_BUTTON + fprintf(stderr, "libspudec: normal button clut\n"); +#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] ); + /* FIXME:Only the first grouping of buttons are used at the moment */ + btn->left = button_ptr->x_start; + btn->top = button_ptr->y_start; + btn->right = button_ptr->x_end; + btn->bottom = button_ptr->y_end; + return 1; + } + return -1; +} + +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; +#if LOG_SPU + printf ("dxr3_spu: event: SPU_FD = %i\n",this->fd_spu); +#endif + + switch (event->event.type) { + case XINE_EVENT_SPU_BUTTON: + { + + spu_button_t *but = event->data; + em8300_button_t btn; +#if LOG_SPU + printf ("dxr3_spu: SPU_BUTTON\n"); +#endif + +// if (!but->show) { +// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); +// break; +// } + + this->buttonN = but->buttonN; + if ( (but->show > 0) && (spudec_copy_nav_to_btn(&this->pci, this->buttonN, but->show - 1, &btn ) > 0)) { + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) { + printf("dxr3: failed to set spu button (%s)\n", + strerror(errno)); + } + } +#if LOG_SPU + printf ("dxr3_spu: buttonN = %u\n",but->buttonN); +#endif + } + break; + + case XINE_EVENT_SPU_CLUT: + { + spudec_clut_table_t *clut = event->data; +#if LOG_SPU + printf ("dxr3_spu: SPU_CLUT\n"); +#endif +#if LOG_SPU + printf ("dxr3_spu: clut: SPU_FD = %i\n",this->fd_spu); +#endif +#ifdef WORDS_BIGENDIAN + swab_clut(clut->clut); +#endif + + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, clut->clut)) + printf("dxr3: failed to set CLUT (%s)\n", + strerror(errno)); + } + break; + /* Temporarily use the stream title to find out if we have a menu... + obsoleted by XINE_EVENT_SPU_FORCEDISPLAY, but we'll keep it 'til + the next version of dvdnav */ + case XINE_EVENT_UI_SET_TITLE: + { + if(strstr(event->data,"Menu")) + this->menu=1; + else + this->menu=0; + } + break; + case XINE_EVENT_SPU_FORCEDISPLAY: + { + (int*)this->menu=event->data; + } + break; + default: + { + } + + } +} + +static char *spudec_get_id(void) +{ + return "dxr3-spudec"; +} + +static void spudec_dispose (spu_decoder_t *this_gen) { + spudec_decoder_t *this = (spudec_decoder_t *) this_gen; + + xine_remove_event_listener (this->xine, spudec_event_listener); + + free (this); +} + +spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) +{ + spudec_decoder_t *this; + config_values_t *cfg; + char *tmpstr; + int dashpos; + int result; + + if (iface_version != 7) { + printf( "dxr3_decode_spu: plugin doesn't support plugin API version %d.\n" + "dxr3_decode_spu: this means there's a version mismatch between xine and this " + "dxr3_decode_spu: decoder plugin.\nInstalling current plugins should help.\n", + iface_version); + return NULL; + } + + cfg = xine->config; + tmpstr = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL); + strncpy(devname, tmpstr, 128); + devname[127] = '\0'; + dashpos = strlen(devname) - 2; /* the dash in the new device naming scheme would be here */ + if (devname[dashpos] == '-') { + /* use new device naming scheme with trailing number */ + strncpy(devnum, &devname[dashpos], 3); + devname[dashpos] = '\0'; + } else { + /* use old device naming scheme without trailing number */ + /* FIXME: remove this when everyone uses em8300 >=0.12.0 */ + devnum[0] = '\0'; + } + + result = dxr3_presence_test ( xine ); + if (!result) { + return NULL; + } + + this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t)); + + this->spu_decoder.interface_version = iface_version; + 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.reset = spudec_reset; + this->spu_decoder.close = spudec_close; + this->spu_decoder.get_identifier = spudec_get_id; + this->spu_decoder.dispose = spudec_dispose; + this->spu_decoder.priority = 10; + this->xine = xine; + this->menu = 0; + this->fd_spu = 0; + this->pci.hli.hl_gi.hli_ss = 0; + this->pci.hli.hl_gi.hli_s_ptm = 0; + this->buttonN = 1; + this->button_vpts = 0; + + xine_register_event_listener(xine, spudec_event_listener, this); + + return (spu_decoder_t *) this; +} diff --git a/src/dxr3/dxr3_decoder.c b/src/dxr3/dxr3_decode_video.c index 68480d9d8..9e2fbcf1a 100644 --- a/src/dxr3/dxr3_decoder.c +++ b/src/dxr3/dxr3_decode_video.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_decoder.c,v 1.76 2002/05/01 22:58:42 jcdutton Exp $ + * $Id: dxr3_decode_video.c,v 1.1 2002/05/02 14:33:30 jcdutton Exp $ * * dxr3 video and spu decoder plugin. Accepts the video and spu data * from XINE and sends it directly to the corresponding dxr3 devices. @@ -104,6 +104,7 @@ typedef struct dxr3_decoder_s { video_decoder_t video_decoder; vo_instance_t *video_out; config_values_t *config; + metronom_t *metronom; int fd_control; int fd_video; @@ -127,25 +128,17 @@ typedef struct dxr3_decoder_s { pthread_t decoder_thread; /* reference to self */ } dxr3_decoder_t; -static int dxr3_tested = 0; -static int dxr3_ok; - -int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn ); - -static void dxr3_presence_test( xine_t* xine) +static int dxr3_presence_test( xine_t* xine) { int info; -/* FIXME: Get rid of global vars */ - dxr3_tested = 1; - dxr3_ok = 0; if (xine && xine->video_driver ) { info = xine->video_driver->get_property( xine->video_driver, VO_PROP_VO_TYPE); printf("dxr3_presence_test:info=%d\n",info); if (info != VO_TYPE_DXR3) { - return; + return 0; } } - dxr3_ok = 1; + return 1; } @@ -370,7 +363,7 @@ static int dxr3_can_handle (video_decoder_t *this_gen, int buf_type) static void dxr3_init (video_decoder_t *this_gen, vo_instance_t *video_out) { dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen; - metronom_t *metronom = this->video_decoder.metronom; + metronom_t *metronom = this->metronom; char tmpstr[128]; int64_t cur_offset; @@ -629,14 +622,14 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) if (!this->scr) { int64_t time; - time = this->video_decoder.metronom->get_current_time( - this->video_decoder.metronom); + time = this->metronom->get_current_time( + this->metronom); this->scr = dxr3scr_init(this); this->scr->start(this->scr, time); - this->video_decoder.metronom->register_scr( - this->video_decoder.metronom, this->scr); - if (this->video_decoder.metronom->scr_master == this->scr) { + this->metronom->register_scr( + this->metronom, this->scr); + if (this->metronom->scr_master == this->scr) { printf("dxr3: dxr3scr plugin is master\n"); } else { printf("dxr3: dxr3scr plugin is NOT master\n"); @@ -649,8 +642,8 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { int64_t delay; - delay = vpts - this->video_decoder.metronom->get_current_time( - this->video_decoder.metronom); + delay = vpts - this->metronom->get_current_time( + this->metronom); #if LOG_PTS printf("dxr3: SETPTS got %lld expected = %lld (delta %lld) delay = %lld\n", vpts, this->last_pts, vpts-this->last_pts, delay); @@ -706,7 +699,7 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) static void dxr3_close (video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen; - metronom_t *metronom = this->video_decoder.metronom; + metronom_t *metronom = this->metronom; int64_t cur_offset; if (this->scr) { @@ -772,11 +765,12 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, config_values_t *cfg; char *tmpstr; int dashpos; + int result; - if (iface_version != 7) { - printf( "dxr3: plugin doesn't support plugin API version %d.\n" - "dxr3: this means there's a version mismatch between xine and this\n" - "dxr3: decoder plugin. Installing current plugins should help.\n", + if (iface_version != 8) { + printf( "dxr3_decode_video: plugin doesn't support plugin API version %d.\n" + "dxr3_decode_video: this means there's a version mismatch between xine and this\n" + "dxr3_decode_video: decoder plugin. Installing current plugins should help.\n", iface_version); return NULL; } @@ -796,8 +790,8 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, devnum[0] = '\0'; } - dxr3_presence_test ( xine ); - if (!dxr3_ok) return NULL; + result = dxr3_presence_test ( xine ); + if (!result) return NULL; this = (dxr3_decoder_t *) malloc (sizeof (dxr3_decoder_t)); @@ -814,7 +808,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, "dxr3.decoder_priority", 10, "Dxr3: video decoder priority", NULL, NULL, NULL); this->config = cfg; - + this->metronom = xine->metronom; this->frame_rate_code = 0; this->repeat_first_field = 0; this->sync_every_frame = 1; @@ -850,418 +844,3 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, return (video_decoder_t *) this; } -/* - * Second part of the dxr3 plugin: subpicture decoder - */ -#define MAX_SPU_STREAMS 32 - -typedef struct spudec_stream_state_s { - uint32_t stream_filter; -} spudec_stream_state_t; - -typedef struct spudec_decoder_s { - spu_decoder_t spu_decoder; - spudec_stream_state_t spu_stream_state[MAX_SPU_STREAMS]; - - vo_instance_t *vo_out; - int fd_spu; - int menu; /* are we in a menu? */ - pci_t pci; - uint32_t buttonN; /* currently highlighted button */ - int64_t button_vpts; /* time to show the menu enter button */ - xine_t *xine; -} spudec_decoder_t; - -static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) -{ - int type = buf_type & 0xFFFF0000; - return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT || - type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL); -} - -static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) -{ - spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - char tmpstr[100]; - int i; - - this->vo_out = vo_out; - - /* open spu device */ - snprintf (tmpstr, sizeof(tmpstr), "%s_sp%s", devname, devnum); - if ((this->fd_spu = open (tmpstr, O_WRONLY)) < 0) { - printf("dxr3: Failed to open spu device %s (%s)\n", - tmpstr, strerror(errno)); - return; - } -#if LOG_SPU - printf ("dxr3_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 */ - this->spu_stream_state[i].stream_filter = 1; -} - -static void swab_clut(int* clut) -{ - int i; - for (i=0; i<16; i++) - clut[i] = bswap_32(clut[i]); -} - -static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) -{ - spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - ssize_t written; - uint32_t stream_id = buf->type & 0x1f ; - - if (this->button_vpts && - this->spu_decoder.metronom->get_current_time(this->spu_decoder.metronom) > this->button_vpts) { - /* we have a scheduled menu enter button and it's time to show it now */ - em8300_button_t button; - int buttonNr; - btni_t *button_ptr; - - buttonNr = this->buttonN; - - if (this->pci.hli.hl_gi.fosl_btnn > 0) - buttonNr = this->pci.hli.hl_gi.fosl_btnn ; - - if ((buttonNr <= 0) || (buttonNr > this->pci.hli.hl_gi.btn_ns)) { - printf("dxr3_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n", buttonNr); - buttonNr = 1; - } - - button_ptr = &this->pci.hli.btnit[buttonNr-1]; - button.left = button_ptr->x_start; - button.top = button_ptr->y_start; - button.right = button_ptr->x_end; - button.bottom = button_ptr->y_end; - button.color = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> 16; - button.contrast = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] & 0xffff; - -#if LOG_SPU - printf("dxr3_spu: now showing menu enter button %i.\n", buttonNr); -#endif - ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &button); - this->button_vpts = 0; - this->pci.hli.hl_gi.hli_s_ptm = 0; - } - - if (buf->type == BUF_SPU_CLUT) { -#if LOG_SPU - printf ("dxr3_spu: BUF_SPU_CLUT\n" ); -#endif -#if LOG_SPU - printf ("dxr3_spu: buf clut: SPU_FD = %i\n",this->fd_spu); -#endif - if (buf->content[0] == 0) /* cheap endianess detection */ - swab_clut((int*)buf->content); - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, buf->content)) - printf("dxr3: failed to set CLUT (%s)\n", strerror(errno)); - return; - } - if(buf->type == BUF_SPU_SUBP_CONTROL){ -/*************** - int i; - uint32_t *subp_control = (uint32_t*) buf->content; - for (i = 0; i < 32; i++) { - this->spu_stream_state[i].stream_filter = subp_control[i]; - } -***************/ - return; - } - if(buf->type == BUF_SPU_NAV){ -#if LOG_SPU - printf("dxr3_spu: Got NAV packet\n"); -#endif - uint8_t *p = buf->content; - - /* just watch out for menus */ - if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */ - pci_t pci; - - nav_read_pci(&pci, p + 7); - - if (pci.hli.hl_gi.hli_ss == 1) { - em8300_button_t btn; - /* menu ahead, remember pci for later evaluation */ - xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t)); - if ( (spudec_copy_nav_to_btn(&this->pci, this->buttonN, 0, &btn ) > 0)) { - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) { - printf("dxr3: failed to set spu button (%s)\n", - strerror(errno)); - } - } - } - - if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) { - /* leaving menu */ - xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t)); - ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); - } - } - return; - } - /* Is this also needed for subpicture? */ - if (buf->decoder_flags & BUF_FLAG_PREVIEW) { -#if LOG_SPU - printf ("dxr3_spu: Dropping SPU channel %d. Preview data\n", stream_id); -#endif - return; - } - - if ( this->spu_stream_state[stream_id].stream_filter == 0) { -#if LOG_SPU - printf ("dxr3_spu: Dropping SPU channel %d. Stream filtered\n", stream_id); -#endif - return; - } -/* 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 ) { -#if LOG_SPU - printf ("dxr3_spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id); -#endif - return; - } - if ( (this->menu == 0) && (this->xine->spu_channel & 0x80) ) { -#if LOG_SPU - printf ("dxr3_spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id); -#endif - return; - } -// if (this->xine->spu_channel != stream_id && this->menu!=1 ) return; - /* Hide any previous button highlights */ -// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); - if (buf->pts) { - int64_t vpts; - uint32_t vpts32; - - vpts = this->spu_decoder.metronom->got_spu_packet - (this->spu_decoder.metronom, buf->pts); -#if LOG_SPU - printf ("dxr3_spu: pts=%lld vpts=%lld\n", buf->pts, vpts); -#endif - vpts32 = vpts; - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32)) - printf("dxr3: spu setpts failed (%s)\n", strerror(errno)); - - if (buf->pts == this->pci.hli.hl_gi.hli_s_ptm) - /* schedule the menu enter button for current packet's vpts, so - that the card has decoded this SPU when we try to show the button */ - this->button_vpts = vpts; - } - - -#if LOG_SPU - printf ("dxr3_spu: write: SPU_FD = %i\n",this->fd_spu); -#endif - written = write(this->fd_spu, buf->content, buf->size); - if (written < 0) { - printf("dxr3: spu device write failed (%s)\n", - strerror(errno)); - return; - } - if (written != buf->size) - printf("dxr3: Could only write %d of %d spu bytes.\n", - written, buf->size); -} - -static void spudec_reset (spu_decoder_t *this_gen) -{ -} - -static void spudec_close (spu_decoder_t *this_gen) -{ - spudec_decoder_t *this = (spudec_decoder_t *) this_gen; -#if LOG_SPU - printf ("dxr3_spu: close: SPU_FD = %i\n",this->fd_spu); -#endif - - close(this->fd_spu); - this->fd_spu = 0; -} - -int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn ) { - btni_t *button_ptr; - - /* 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 > nav_pci->hli.hl_gi.btn_ns)) { - printf("dxr3_decoder:Unable to select button number %i as it doesn't exist. Forcing button 1\n", - button); - button = 1; - } - /* There is no point in highlighting an area it the area's colours are no different from the general overlay colours. */ - button_ptr = &nav_pci->hli.btnit[button-1]; - if(button_ptr->btn_coln != 0) { -#ifdef LOG_BUTTON - fprintf(stderr, "libspudec: normal button clut\n"); -#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] ); - /* FIXME:Only the first grouping of buttons are used at the moment */ - btn->left = button_ptr->x_start; - btn->top = button_ptr->y_start; - btn->right = button_ptr->x_end; - btn->bottom = button_ptr->y_end; - return 1; - } - return -1; -} - -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; -#if LOG_SPU - printf ("dxr3_spu: event: SPU_FD = %i\n",this->fd_spu); -#endif - - switch (event->event.type) { - case XINE_EVENT_SPU_BUTTON: - { - - spu_button_t *but = event->data; - em8300_button_t btn; -#if LOG_SPU - printf ("dxr3_spu: SPU_BUTTON\n"); -#endif - -// if (!but->show) { -// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); -// break; -// } - - this->buttonN = but->buttonN; - if ( (but->show > 0) && (spudec_copy_nav_to_btn(&this->pci, this->buttonN, but->show - 1, &btn ) > 0)) { - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) { - printf("dxr3: failed to set spu button (%s)\n", - strerror(errno)); - } - } -#if LOG_SPU - printf ("dxr3_spu: buttonN = %u\n",but->buttonN); -#endif - } - break; - - case XINE_EVENT_SPU_CLUT: - { - spudec_clut_table_t *clut = event->data; -#if LOG_SPU - printf ("dxr3_spu: SPU_CLUT\n"); -#endif -#if LOG_SPU - printf ("dxr3_spu: clut: SPU_FD = %i\n",this->fd_spu); -#endif -#ifdef WORDS_BIGENDIAN - swab_clut(clut->clut); -#endif - - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, clut->clut)) - printf("dxr3: failed to set CLUT (%s)\n", - strerror(errno)); - } - break; - /* Temporarily use the stream title to find out if we have a menu... - obsoleted by XINE_EVENT_SPU_FORCEDISPLAY, but we'll keep it 'til - the next version of dvdnav */ - case XINE_EVENT_UI_SET_TITLE: - { - if(strstr(event->data,"Menu")) - this->menu=1; - else - this->menu=0; - } - break; - case XINE_EVENT_SPU_FORCEDISPLAY: - { - (int*)this->menu=event->data; - } - break; - default: - { - } - - } -} - -static char *spudec_get_id(void) -{ - return "dxr3-spudec"; -} - -static void spudec_dispose (spu_decoder_t *this_gen) { - spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - - xine_remove_event_listener (this->xine, spudec_event_listener); - - free (this); -} - -spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) -{ - spudec_decoder_t *this; - config_values_t *cfg; - char *tmpstr; - int dashpos; - - if (iface_version != 6) { - printf( "dxr3: plugin doesn't support plugin API version %d.\n" - "dxr3: this means there's a version mismatch between xine and this " - "dxr3: decoder plugin.\nInstalling current plugins should help.\n", - iface_version); - return NULL; - } - - cfg = xine->config; - tmpstr = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL); - strncpy(devname, tmpstr, 128); - devname[127] = '\0'; - dashpos = strlen(devname) - 2; /* the dash in the new device naming scheme would be here */ - if (devname[dashpos] == '-') { - /* use new device naming scheme with trailing number */ - strncpy(devnum, &devname[dashpos], 3); - devname[dashpos] = '\0'; - } else { - /* use old device naming scheme without trailing number */ - /* FIXME: remove this when everyone uses em8300 >=0.12.0 */ - devnum[0] = '\0'; - } - - dxr3_presence_test ( xine ); - if (!dxr3_ok) { - return NULL; - } - - this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t)); - - this->spu_decoder.interface_version = iface_version; - 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.reset = spudec_reset; - this->spu_decoder.close = spudec_close; - this->spu_decoder.get_identifier = spudec_get_id; - this->spu_decoder.dispose = spudec_dispose; - this->spu_decoder.priority = 10; - this->xine = xine; - this->menu = 0; - this->fd_spu = 0; - this->pci.hli.hl_gi.hli_ss = 0; - this->pci.hli.hl_gi.hli_s_ptm = 0; - this->buttonN = 1; - this->button_vpts = 0; - - xine_register_event_listener(xine, spudec_event_listener, this); - - return (spu_decoder_t *) this; -} |