diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dxr3/Makefile.am | 4 | ||||
-rw-r--r-- | src/dxr3/bswap.h | 87 | ||||
-rw-r--r-- | src/dxr3/dxr3_decoder.c | 275 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.c | 65 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.h | 6 | ||||
-rw-r--r-- | src/dxr3/dxr3_vo_core.c | 4 | ||||
-rw-r--r-- | src/dxr3/nav_read.c | 207 | ||||
-rw-r--r-- | src/dxr3/nav_read.h | 41 | ||||
-rw-r--r-- | src/dxr3/nav_types.h | 404 |
9 files changed, 965 insertions, 128 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index 35fcd88da..eaff0136f 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -1,6 +1,6 @@ CFLAGS = @GLOBAL_CFLAGS@ @X_CFLAGS@ $(LINUX_INCLUDE) -EXTRA_DIST = dxr3_decoder.c dxr3_vo_core.c dxr3_video_out.c +EXTRA_DIST = dxr3_decoder.c dxr3_vo_core.c dxr3_video_out.c nav_read.c LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic @@ -18,7 +18,7 @@ endif lib_LTLIBRARIES = $(dxr3_modules) -xineplug_decode_dxr3_la_SOURCES = dxr3_decoder.c +xineplug_decode_dxr3_la_SOURCES = dxr3_decoder.c nav_read.c xineplug_decode_dxr3_la_LDFLAGS = -avoid-version -module xineplug_vo_out_dxr3_la_SOURCES = dxr3_video_out.c \ diff --git a/src/dxr3/bswap.h b/src/dxr3/bswap.h new file mode 100644 index 000000000..23e2863b4 --- /dev/null +++ b/src/dxr3/bswap.h @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2000, 2001 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * This program 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. + * + * This program 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 + */ + +#ifndef BSWAP_H_INCLUDED +#define BSWAP_H_INCLUDED + +#include <config.h> + +#if defined(WORDS_BIGENDIAN) +/* All bigendian systems are fine, just ignore the swaps. */ +#define B2N_16(x) (void)(x) +#define B2N_32(x) (void)(x) +#define B2N_64(x) (void)(x) + +#else + +#if defined(__linux__) +#include <byteswap.h> +#define B2N_16(x) x = bswap_16(x) +#define B2N_32(x) x = bswap_32(x) +#define B2N_64(x) x = bswap_64(x) + +#elif defined(__NetBSD__) +#include <sys/endian.h> +#define B2N_16(x) BE16TOH(x) +#define B2N_32(x) BE32TOH(x) +#define B2N_64(x) BE64TOH(x) + +#elif defined(__OpenBSD__) +#include <sys/endian.h> +#define B2N_16(x) x = swap16(x) +#define B2N_32(x) x = swap32(x) +#define B2N_64(x) x = swap64(x) + +/* This is a slow but portable implementation, it has multiple evaluation + * problems so beware. + * FreeBSD and Solaris don't have <byteswap.h> or any other such + * functionality! + */ + +#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) +#define B2N_16(x) \ + x = ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) +#define B2N_32(x) \ + x = ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) +#define B2N_64(x) \ + x = ((((x) & 0xff00000000000000) >> 56) | \ + (((x) & 0x00ff000000000000) >> 40) | \ + (((x) & 0x0000ff0000000000) >> 24) | \ + (((x) & 0x000000ff00000000) >> 8) | \ + (((x) & 0x00000000ff000000) << 8) | \ + (((x) & 0x0000000000ff0000) << 24) | \ + (((x) & 0x000000000000ff00) << 40) | \ + (((x) & 0x00000000000000ff) << 56)) + +#else + +/* If there isn't a header provided with your system with this functionality + * add the relevant || define( ) to the portable implementation above. + */ +#error "You need to add endian swap macros for you're system" + +#endif + +#endif /* WORDS_BIGENDIAN */ + +#endif /* BSWAP_H_INCLUDED */ diff --git a/src/dxr3/dxr3_decoder.c b/src/dxr3/dxr3_decoder.c index 78cabfe3b..e40b6c318 100644 --- a/src/dxr3/dxr3_decoder.c +++ b/src/dxr3/dxr3_decoder.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.61 2002/03/05 21:54:31 jcdutton Exp $ + * $Id: dxr3_decoder.c,v 1.62 2002/03/07 13:33:44 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. @@ -78,20 +78,22 @@ #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; +static char devname[128]; +static char devnum[3]; /* lots of poohaa about pts things */ -#define LOG_PTS 0 +#define LOG_PTS 0 #define LOG_SPU 0 #define MV_COMMAND 0 -#define MV_STATUS 1 #ifndef MVCOMMAND_SCAN #define MVCOMMAND_SCAN 4 #endif @@ -104,7 +106,7 @@ typedef struct dxr3_decoder_s { int fd_control; int fd_video; - int last_pts; + int64_t last_pts; scr_plugin_t *scr; int scr_prio; int width; @@ -112,7 +114,7 @@ typedef struct dxr3_decoder_s { int aspect; int frame_rate_code; int repeat_first_field; - /* try to sync PTS every frame. will be disabled if non-progessive + /* try to sync pts every frame. will be disabled if non-progessive video is detected via repeat first field */ int sync_every_frame; /* if disabled by repeat first field, retry after 500 frames */ @@ -123,17 +125,6 @@ typedef struct dxr3_decoder_s { pthread_t decoder_thread; /* reference to self */ } dxr3_decoder_t; -/* Function to check whether the dxr3 video out plugin is active. - * Without it, we can't work and must give it to libmpeg2. - * We (ab)use a config value for this (set by dxr3 video out init/exit) - */ -static int dxr3_check_vo(config_values_t* cfg) -{ - cfg_entry_t* entry; - entry = cfg->lookup_entry(cfg, "dxr3.active"); - return (entry && entry->num_value); -} - static int dxr3_tested = 0; static int dxr3_ok; @@ -162,7 +153,7 @@ static void dxr3_presence_test( xine_t* xine) 4 - Play intra frames only (for FFWD/FBackward) 6 - Alternate playmode - not much is known about this mode other than it buffers frames, possibly re-organising them - on-the-fly to match SCR vs PTS values + on-the-fly to match scr vs pts values 0x11 - Flush the onboard buffer??????? 0x10 - as above??? */ @@ -179,7 +170,8 @@ typedef struct dxr3scr_s { scr_plugin_t scr; int fd_control; int priority; - int offset; /* a little offset < 7200 */ + int64_t offset; /* difference between real scr and internal dxr3 clock */ + uint32_t last_pts; /* last known value of internal dxr3 clock to detect wrap around */ } dxr3scr_t; static int dxr3scr_get_priority (scr_plugin_t *scr) { @@ -244,25 +236,33 @@ static int dxr3scr_set_speed (scr_plugin_t *scr, int speed) { /* *** dxr3scr_adjust *** - Adjusts the SCR value of the card to match that given. - This function is only called if the dxr3 SCR plugin is + Adjusts the scr value of the card to match that given. + This function is only called if the dxr3 scr plugin is _NOT_ master... Harm: wish that were so. It's called by audio_out (those adjusting master clock x->y messages) */ static void dxr3scr_adjust (scr_plugin_t *scr, int64_t vpts) { dxr3scr_t *self = (dxr3scr_t*) scr; - uint32_t cpts; - if (ioctl(self->fd_control, EM8300_IOCTL_SCR_GET, &cpts)) + uint32_t cpts32; + int32_t offset32; + int64_t cpts; + + if (ioctl(self->fd_control, EM8300_IOCTL_SCR_GET, &cpts32)) printf("dxr3scr: adjust get failed (%s)\n", strerror(errno)); - cpts <<= 1; + cpts = (int64_t)cpts32 << 1; + self->last_pts = cpts32; self->offset = vpts - cpts; - /* kernel driver ignores diffs < 7200 */ - if (self->offset < -7200 || self->offset > 7200) { - vpts >>= 1; - if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SET, &vpts)) + offset32 = self->offset / 4; + /* kernel driver ignores diffs < 7200, so abs(offste32) must be > 7200 / 4 */ + if (offset32 < -7200/4 || offset32 > 7200/4) { + uint32_t vpts32 = vpts >> 1; + if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SET, &vpts32)) printf("dxr3scr: adjust set failed (%s)\n", strerror(errno)); - self->offset = 0; + self->last_pts = vpts32; + self->offset &= ~0x1FFFFFFFF; + /* the internal clock in the dxr3 is 33 bits wide, so the upper bits + remain as an offset */ } } @@ -273,14 +273,15 @@ static void dxr3scr_adjust (scr_plugin_t *scr, int64_t vpts) { */ static void dxr3scr_start (scr_plugin_t *scr, int64_t start_vpts) { dxr3scr_t *self = (dxr3scr_t*) scr; - start_vpts >>= 1; + uint32_t vpts32 = start_vpts >> 1; - self->offset = 0; - if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SET, &start_vpts)) + self->last_pts = vpts32; + self->offset = start_vpts & ~0x1FFFFFFFF; + if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SET, &vpts32)) printf("dxr3scr: start failed (%s)\n", strerror(errno)); - /* mis-use start_vpts */ - start_vpts = 0x900; - ioctl(self->fd_control, EM8300_IOCTL_SCR_SETSPEED, &start_vpts); + /* mis-use vpts32 */ + vpts32 = 0x900; + ioctl(self->fd_control, EM8300_IOCTL_SCR_SETSPEED, &vpts32); } @@ -295,8 +296,11 @@ static int64_t dxr3scr_get_current (scr_plugin_t *scr) { if (ioctl(self->fd_control, EM8300_IOCTL_SCR_GET, &pts)) printf("dxr3scr: get current failed (%s)\n", strerror(errno)); + if (pts < self->last_pts) /* wrap around detected, compensate with offset */ + self->offset += (int64_t)1 << 33; + self->last_pts = pts; - return (pts << 1) + self->offset; + return ((int64_t)pts << 1) + self->offset; } @@ -305,6 +309,7 @@ static int64_t dxr3scr_get_current (scr_plugin_t *scr) { */ static scr_plugin_t* dxr3scr_init (dxr3_decoder_t *dxr3) { dxr3scr_t *self; + char tmpstr[128]; self = malloc(sizeof(*self)); memset(self, 0, sizeof(*self)); @@ -317,10 +322,12 @@ static scr_plugin_t* dxr3scr_init (dxr3_decoder_t *dxr3) { self->scr.get_current = dxr3scr_get_current; self->offset = 0; + self->last_pts = 0; - if ((self->fd_control = open (devname, O_WRONLY)) < 0) { + snprintf (tmpstr, sizeof(tmpstr), "%s%s", devname, devnum); + if ((self->fd_control = open (tmpstr, O_WRONLY)) < 0) { printf("dxr3scr: Failed to open control device %s (%s)\n", - devname, strerror(errno)); + tmpstr, strerror(errno)); return NULL; } @@ -332,10 +339,6 @@ static scr_plugin_t* dxr3scr_init (dxr3_decoder_t *dxr3) { static int dxr3_can_handle (video_decoder_t *this_gen, int buf_type) { - if (! dxr3_check_vo(((dxr3_decoder_t*)this_gen)->config)) { - /* dxr3 video out is not active. Play dead. */ - return 0; - } buf_type &= 0xFFFF0000; return (buf_type == BUF_VIDEO_MPEG); } @@ -343,36 +346,41 @@ 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; + char tmpstr[128]; - printf("dxr3: Entering video init, devname=%s.\n",devname); + snprintf (tmpstr, sizeof(tmpstr), "%s%s", devname, devnum); + printf("dxr3: Entering video init, devname=%s.\n",tmpstr); this->fd_video = -1; /* open later */ - if ((this->fd_control = open (devname, O_WRONLY)) < 0) { + if ((this->fd_control = open (tmpstr, O_WRONLY)) < 0) { printf("dxr3: Failed to open control device %s (%s)\n", - devname, strerror(errno)); + tmpstr, strerror(errno)); return; } video_out->open(video_out); this->video_out = video_out; - this->last_pts = 0; + this->last_pts = this->video_decoder.metronom-> + get_current_time(this->video_decoder.metronom); this->decoder_thread = pthread_self(); - this->scr = dxr3scr_init(this); - this->video_decoder.metronom->register_scr( - this->video_decoder.metronom, this->scr); + if (!this->scr) { + this->scr = dxr3scr_init(this); + /* dxr3_init is called while the master scr already runs. + therefore the scr must be started here */ + this->scr->start(this->scr, this->video_decoder.metronom-> + get_current_time(this->video_decoder.metronom)); + this->video_decoder.metronom->register_scr( + this->video_decoder.metronom, this->scr); - if (this->video_decoder.metronom->scr_master == this->scr) { - printf("dxr3: dxr3scr plugin is master\n"); - } - else { - printf("dxr3: dxr3scr plugin is NOT master\n"); + if (this->video_decoder.metronom->scr_master == this->scr) { + printf("dxr3: dxr3scr plugin is master\n"); + } else { + printf("dxr3: dxr3scr plugin is NOT master\n"); + } } - /* dxr3_init is called while the master scr already runs. - therefore the scr must be started here */ - this->scr->start(this->scr, 0); } @@ -446,8 +454,8 @@ static void dxr3_flush (video_decoder_t *this_gen) /* Don't flush, causes still images to disappear. We don't seem * to need it anyway... */ printf("dxr3_decoder: flush requested, disabled for the moment.\n"); - /* dxr3_mvcommand(this->fd_control, 0x11); */ - this->have_header_info = 0; + /* dxr3_mvcommand(this->fd_control, 0x11); + this->have_header_info = 0; */ if (this->fd_video >= 0) fsync(this->fd_video); } @@ -457,7 +465,8 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen; ssize_t written; - int vpts, i, duration, skip; + int64_t vpts; + int i, duration, skip; vo_frame_t *img; uint8_t *buffer, byte; uint32_t shift; @@ -556,15 +565,16 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) DXR3_VO_UPDATE_FLAG); img->pts=buf->pts; img->bad_frame = 0; + img->duration = duration; /* draw calls metronom->got_video_frame with img pts and scr - and stores the return value back in img->PTS + and stores the return value in img->vpts Calling draw with buf->pts==0 is okay; metronome will extrapolate a value. */ skip = img->draw(img); if (skip <= 0) { /* don't skip */ vpts = img->pts; /* copy so we can free img */ } - else { /* metronom says skip, so don't set PTS */ + else { /* metronom says skip, so don't set pts */ printf("dxr3: skip = %d\n", skip); vpts = 0; } @@ -590,7 +600,7 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) * wants to open it) */ if (this->fd_video < 0) { char tmpstr[128]; - snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname); + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", devname, devnum); if ((this->fd_video = open (tmpstr, O_WRONLY | O_NONBLOCK)) < 0) { printf("dxr3: Failed to open video device %s (%s)\n", tmpstr, strerror(errno)); @@ -602,26 +612,27 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) * FIXME: the exact conditions here are a bit uncertain... */ if (vpts) { - int delay; + int64_t delay; delay = vpts - this->video_decoder.metronom->get_current_time( this->video_decoder.metronom); #if LOG_PTS - printf("dxr3: SETPTS got %d expected = %d (delta %d) delay = %d\n", + printf("dxr3: SETPTS got %lld expected = %lld (delta %lld) delay = %lld\n", vpts, this->last_pts, vpts-this->last_pts, delay); #endif this->last_pts = vpts; /* SETPTS only if less then one second in the future and - * either buffer has PTS or sync_every_frame is set */ + * either buffer has pts or sync_every_frame is set */ if ((delay > 0) && (delay < 90000) && (this->sync_every_frame || buf->pts)) { + uint32_t vpts32 = vpts; /* update the dxr3's current pts value */ - if (ioctl(this->fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vpts)) + if (ioctl(this->fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vpts32)) printf("dxr3: set video pts failed (%s)\n", strerror(errno)); } if (delay >= 90000) { /* frame more than 1 sec ahead */ - printf("dxr3: WARNING: vpts %d is %.02f seconds ahead of time!\n", + printf("dxr3: WARNING: vpts %lld is %.02f seconds ahead of time!\n", vpts, delay/90000.0); } if (delay < 0) { @@ -630,7 +641,7 @@ static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf) } #if LOG_PTS else if (buf->pts) { - printf("dxr3: skip buf->PTS = %Lu (no vpts) last_vpts = %d\n", + printf("dxr3: skip buf->pts = %lld (no vpts) last_vpts = %lld\n", buf->pts, this->last_pts); } #endif @@ -714,6 +725,8 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, { dxr3_decoder_t *this ; config_values_t *cfg; + char *tmpstr; + int dashpos; if (iface_version != 5) { printf( "dxr3: plugin doesn't support plugin API version %d.\n" @@ -724,7 +737,19 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, } cfg = xine->config; - devname = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, "Dxr3: Device Name",NULL,NULL,NULL); + tmpstr = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, "Dxr3: Device Name",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; @@ -745,6 +770,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, this->repeat_first_field = 0; this->sync_every_frame = 1; + this->scr = NULL; this->scr_prio = cfg->register_num(cfg, "dxr3.scr_priority", 10, "Dxr3: SCR plugin priority",NULL,NULL,NULL); this->sync_every_frame = cfg->register_bool(cfg, @@ -791,16 +817,15 @@ typedef struct spudec_decoder_s { 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; - if (! dxr3_check_vo(((spudec_decoder_t*)this_gen)->xine->config) ) { - /* dxr3 video out is not active. Play dead. */ - return 0; - } return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT || type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL); } @@ -814,7 +839,7 @@ static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) this->vo_out = vo_out; /* open spu device */ - snprintf (tmpstr, sizeof(tmpstr), "%s_sp", devname); + 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)); @@ -841,6 +866,39 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) 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" ); @@ -866,9 +924,28 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) } if(buf->type == BUF_SPU_NAV){ #if LOG_SPU - printf ("dxr3_spu: Got NAV packet\n"); + printf("dxr3_spu: Got NAV packet\n"); #endif - return; + uint8_t *p; + pci_t *pci; + + p = buf->content; + /* just watch out for menus */ + if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */ + pci=xine_xmalloc(sizeof(pci_t)); + nav_read_pci(pci, p + 7); + + if (pci->hli.hl_gi.hli_ss == 1) + /* menu ahead, remember pci for later evaluation */ + 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)) { + /* 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_info[0] == 0) { @@ -892,19 +969,32 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) #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) { - int vpts; + int64_t vpts; + uint32_t vpts32; + vpts = this->spu_decoder.metronom->got_spu_packet (this->spu_decoder.metronom, buf->pts, 0, buf->scr); #if LOG_SPU - printf ("dxr3_spu: PTS=%Lu VPTS=%u\n", buf->pts, vpts); + printf ("dxr3_spu: pts=%lld vpts=%lld\n", buf->pts, vpts); #endif - - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts)) + 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; } @@ -956,6 +1046,9 @@ static void spudec_event_listener (void *this_gen, xine_event_t *event_gen) { // ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); break; } + + this->buttonN = but->buttonN; + btn.color = btn.contrast = 0; #if LOG_SPU printf ("dxr3_spu: buttonN = %u\n",but->buttonN); @@ -1027,6 +1120,8 @@ 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 != 4) { printf( "dxr3: plugin doesn't support plugin API version %d.\n" @@ -1037,7 +1132,19 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) } cfg = xine->config; - devname = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL); + 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) { @@ -1056,6 +1163,10 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) 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); diff --git a/src/dxr3/dxr3_video_out.c b/src/dxr3/dxr3_video_out.c index 1fd3a6d7d..c6d612898 100644 --- a/src/dxr3/dxr3_video_out.c +++ b/src/dxr3/dxr3_video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3_video_out.c,v 1.8 2002/03/05 22:31:06 jcdutton Exp $ + * $Id: dxr3_video_out.c,v 1.9 2002/03/07 13:33:44 jcdutton Exp $ * * mpeg1 encoding video out plugin for the dxr3. * @@ -160,32 +160,6 @@ int dxr3_rte_init(dxr3_driver_t *); int dxr3_fame_init(dxr3_driver_t *); #endif -#define MV_COMMAND 0 - -vo_info_t *get_video_out_plugin_info(); - -/* some helper stuff so that the decoder plugin can test for the - * presence of the dxr3 vo driver */ -/* to be called by dxr3 video out init and exit handlers */ -static void dxr3_set_vo(dxr3_driver_t* this, int active) -{ - cfg_entry_t *entry; - config_values_t *config = this->config; - - entry = config->lookup_entry(config, "dxr3.active"); - if (! entry) { - /* register first */ - config->register_num(config, "dxr3.active", active, - "state of dxr3 video out", - "(internal variable; do not edit)", - NULL, NULL); - } - else { - entry->num_value = active; - } - printf("dxr3: %s dxr3 video out.\n", (active ? "enabled" : "disabled")); -} - static uint32_t dxr3_get_capabilities (vo_driver_t *this_gen) { return VO_CAP_YV12 | VO_CAP_YUY2 | @@ -221,6 +195,7 @@ static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen) frame->vo_frame.copy = 0; frame->vo_frame.field = dummy_frame_field; frame->vo_frame.dispose = dxr3_frame_dispose; + frame->vo_frame.driver = this_gen; return (vo_frame_t*) frame; } @@ -237,7 +212,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen, /* reset the copy calls counter (number of calls to dxr3_frame_copy) */ frame->copy_calls = 0; - frame->vo_instance = this; + frame->vo_frame.driver = this_gen; aspect = this->aspectratio; oheight = this->oheight; @@ -255,7 +230,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen, /* FIXME: Disable reset of mpeg_source * video_out.c can call us without the DXR3_VO_UPDATE_FLAG in * the still frames code. Needs a better fix... */ - /* this->mpeg_source = 0; */ + this->mpeg_source = 0; } /* for mpeg source, we don't have to do much. */ @@ -431,7 +406,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen, static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src) { dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen; - dxr3_driver_t *this = frame->vo_instance; + dxr3_driver_t *this = (dxr3_driver_t *) frame_gen->driver; if (this->mpeg_source == 0 && this->enc && this->enc->on_frame_copy) this->enc->on_frame_copy(this, frame, src); } @@ -476,7 +451,6 @@ void dxr3_exit (vo_driver_t *this_gen) if(this->overlay_enabled) dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF); - dxr3_set_vo(this, 0); } void dxr3_update_add_bars(void *data, cfg_entry_t* entry) @@ -508,6 +482,8 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) char tmpstr[100]; const char *encoder; char *available_encoders,*default_encoder; + char *confstr; + int dashpos; /* * allocate plugin struct @@ -542,12 +518,25 @@ printf("dxr3_video_out:init_plugin\n"); this->enhanced_mode = config->register_bool(config,"dxr3.enc_alt_play_mode", 1, "dxr3: use alternate play mode for mpeg encoder playback","Enabling this option will utilise a slightly different play mode",dxr3_update_enhanced_mode,this); /* open control device */ - this->devname = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV,NULL,NULL,NULL,NULL); + confstr = config->register_string (config, LOOKUP_DEV, DEFAULT_DEV,NULL,NULL,NULL,NULL); + strncpy(this->devname, confstr, 128); + this->devname[127] = '\0'; + dashpos = strlen(this->devname) - 2; /* the dash in the new device naming scheme would be here */ + if (this->devname[dashpos] == '-') { + /* use new device naming scheme with trailing number */ + strncpy(this->devnum, &this->devname[dashpos], 3); + this->devname[dashpos] = '\0'; + } else { + /* use old device naming scheme without trailing number */ + /* FIXME: remove this when everyone uses em8300 >=0.12.0 */ + this->devnum[0] = '\0'; + } - printf("dxr3: Entering video init, devname=%s.\n",this->devname); - if ((this->fd_control = open(this->devname, O_WRONLY)) < 0) { + snprintf (tmpstr, sizeof(tmpstr), "%s%s", this->devname, this->devnum); + printf("dxr3: Entering video init, devname=%s.\n",tmpstr); + if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { printf("dxr3: Failed to open control device %s (%s)\n", - this->devname, strerror(errno)); + tmpstr, strerror(errno)); return 0; } /* output mpeg to file instead of dxr3? */ @@ -562,7 +551,7 @@ printf("dxr3_video_out:init_plugin\n"); } else { /* open video device */ - snprintf (tmpstr, sizeof(tmpstr), "%s_mv", this->devname); + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum); if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) { printf("dxr3: failed to open video device %s (%s)\n", tmpstr, strerror(errno)); @@ -617,8 +606,6 @@ printf("dxr3_video_out:init_plugin\n"); ); } - gather_screen_vars(this, visual_gen); - /* default values */ this->overlay_enabled = 0; this->aspectratio = ASPECT_FULL; @@ -626,11 +613,11 @@ printf("dxr3_video_out:init_plugin\n"); dxr3_read_config(this); if (this->overlay_enabled) { + gather_screen_vars(this, visual_gen); dxr3_get_keycolor(this); dxr3_overlay_buggy_preinit(&this->overlay, this->fd_control); } - dxr3_set_vo(this, 1); return &this->vo_driver; } diff --git a/src/dxr3/dxr3_video_out.h b/src/dxr3/dxr3_video_out.h index 0b79c736d..1c5bbe777 100644 --- a/src/dxr3/dxr3_video_out.h +++ b/src/dxr3/dxr3_video_out.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3_video_out.h,v 1.13 2002/02/25 23:44:05 jcdutton Exp $ + * $Id: dxr3_video_out.h,v 1.14 2002/03/07 13:33:44 jcdutton Exp $ * */ @@ -93,7 +93,8 @@ typedef struct dxr3_driver_s { int mpeg_source; /* receiving mpeg data or raw YUV? */ int enhanced_mode; /* enhanced play mode */ em8300_bcs_t bcs; - const char *devname; + char devname[128]; + char devnum[3]; /* for encoder plugin */ encoder_data_t *enc; /* encoder data */ @@ -141,7 +142,6 @@ typedef struct dxr3_frame_s { uint8_t *mem; /* allocated for YV12 or YUY2 buffers */ uint8_t *real_base[3]; /* yuv/yuy2 buffers in mem aligned on 16 */ int format; - dxr3_driver_t *vo_instance; /* points to self, for use in dxr3_frame_copy */ int copy_calls; /* counts calls to dxr3_frame_copy function */ int swap_fields; /* shifts Y buffer one line to exchange odd/even lines*/ } dxr3_frame_t; diff --git a/src/dxr3/dxr3_vo_core.c b/src/dxr3/dxr3_vo_core.c index 538eed248..a22985479 100644 --- a/src/dxr3/dxr3_vo_core.c +++ b/src/dxr3/dxr3_vo_core.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_vo_core.c,v 1.16 2002/03/05 20:39:05 jcdutton Exp $ + * $Id: dxr3_vo_core.c,v 1.17 2002/03/07 13:33:44 jcdutton Exp $ * ************************************************************************* * core functions common to both Standard and RT-Encoding vo plugins * @@ -287,7 +287,7 @@ int dxr3_set_property (vo_driver_t *this_gen, if (value > ASPECT_FULL) value = ASPECT_ANAMORPHIC; this->aspectratio = value; - fullscreen = is_fullscreen(this); + fullscreen = this->overlay_enabled ? is_fullscreen(this) : 0; if (value == ASPECT_ANAMORPHIC) { fprintf(stderr, "dxr3_vo: setting aspect ratio to anamorphic\n"); diff --git a/src/dxr3/nav_read.c b/src/dxr3/nav_read.c new file mode 100644 index 000000000..0a8ac3813 --- /dev/null +++ b/src/dxr3/nav_read.c @@ -0,0 +1,207 @@ +/** + * Copyright (C) 2000 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * This program 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. + * + * This program 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 + */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <assert.h> + +#include "config.h" // Needed for WORDS_BIGENDIAN +#include "bswap.h" +#include "nav_types.h" +#include "nav_read.h" + +void nav_read_pci(pci_t *pci, unsigned char *buffer) { + int i, j; + + assert(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id + + memcpy(pci, buffer, sizeof(pci_t)); + + /* Endian conversions */ + + /* pci pci_gi */ + B2N_32(pci->pci_gi.nv_pck_lbn); + B2N_16(pci->pci_gi.vobu_cat); + B2N_32(pci->pci_gi.vobu_s_ptm); + B2N_32(pci->pci_gi.vobu_e_ptm); + B2N_32(pci->pci_gi.vobu_se_e_ptm); + + /* pci nsml_agli */ + for(i = 0; i < 9; i++) + B2N_32(pci->nsml_agli.nsml_agl_dsta[i]); + + /* pci hli hli_gi */ + B2N_16(pci->hli.hl_gi.hli_ss); + B2N_32(pci->hli.hl_gi.hli_s_ptm); + B2N_32(pci->hli.hl_gi.hli_e_ptm); + B2N_32(pci->hli.hl_gi.btn_se_e_ptm); + + /* pci hli btn_colit */ + for(i = 0; i < 3; i++) + for(j = 0; j < 2; j++) + B2N_32(pci->hli.btn_colit.btn_coli[i][j]); + + + /* pci hli btni */ + /* There are some issues with this bitfiled with some compilers + because they stradle word boundaries. */ + +#if !defined(WORDS_BIGENDIAN) + for(i = 0; i < 36; i++) { +#if 0 /* Wierd Sun CC code that does not work */ + unsigned char m[6]; + memcpy(m, &pci->hli.btnit[i], 6); + pci->hli.btnit[i].zero1 = (m[1] >> 2); + pci->hli.btnit[i].x_start = (m[0] << 4) | (m[1] >> 4); + pci->hli.btnit[i].x_end = (m[1] << 8) | m[2]; + pci->hli.btnit[i].y_start = (m[3] << 4) | (m[4] >> 4); + pci->hli.btnit[i].y_end = (m[4] << 8) | m[5]; + pci->hli.btnit[i].zero2 = (m[4] >> 2); + pci->hli.btnit[i].btn_coln = (m[0] >> 6); + pci->hli.btnit[i].auto_action_mode = (m[3] >> 6); +#else + char tmp[6], swap; + memcpy(tmp, &(pci->hli.btnit[i]), 6); + /* This is a B2N_24() */ + swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap; + /* This is a B2N_24() */ + swap = tmp[3]; tmp[3] = tmp[5]; tmp[5] = swap; + memcpy(&(pci->hli.btnit[i]), tmp, 6); +#endif + } +#endif + + + /* Asserts */ + + /* pci pci gi */ + assert(pci->pci_gi.zero1 == 0); + + /* pci hli hli_gi */ + assert(pci->hli.hl_gi.zero1 == 0); + assert(pci->hli.hl_gi.zero2 == 0); + assert(pci->hli.hl_gi.zero3 == 0); + assert(pci->hli.hl_gi.zero4 == 0); + assert(pci->hli.hl_gi.zero5 == 0); + + /* Are there buttons defined here? */ + if((pci->hli.hl_gi.hli_ss & 0x03) != 0) { + assert(pci->hli.hl_gi.btn_ns != 0); + assert(pci->hli.hl_gi.btngr_ns != 0); + } else { + assert((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) + || (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0)); + } + + /* pci hli btnit */ + +#if NDEBUG + for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { + for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { + int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; + assert(pci->hli.btnit[n].zero1 == 0); + assert(pci->hli.btnit[n].zero2 == 0); + assert(pci->hli.btnit[n].zero3 == 0); + assert(pci->hli.btnit[n].zero4 == 0); + assert(pci->hli.btnit[n].zero5 == 0); + assert(pci->hli.btnit[n].zero6 == 0); + + if (j < pci->hli.hl_gi.btn_ns) { + assert(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); + assert(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); + assert(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); + assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); + assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); + assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); + //vmcmd_verify(pci->hli.btnit[n].cmd); + } else { + int k; + assert(pci->hli.btnit[n].btn_coln == 0); + assert(pci->hli.btnit[n].auto_action_mode == 0); + assert(pci->hli.btnit[n].x_start == 0); + assert(pci->hli.btnit[n].y_start == 0); + assert(pci->hli.btnit[n].x_end == 0); + assert(pci->hli.btnit[n].y_end == 0); + assert(pci->hli.btnit[n].up == 0); + assert(pci->hli.btnit[n].down == 0); + assert(pci->hli.btnit[n].left == 0); + assert(pci->hli.btnit[n].right == 0); + for (k = 0; k < 8; k++) + assert(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO? + } + } + } +#endif +} + +void nav_read_dsi(dsi_t *dsi, unsigned char *buffer) { + int i; + + assert(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id + + memcpy(dsi, buffer, sizeof(dsi_t)); + + /* Endian conversions */ + + /* dsi dsi gi */ + B2N_32(dsi->dsi_gi.nv_pck_scr); + B2N_32(dsi->dsi_gi.nv_pck_lbn); + B2N_32(dsi->dsi_gi.vobu_ea); + B2N_32(dsi->dsi_gi.vobu_1stref_ea); + B2N_32(dsi->dsi_gi.vobu_2ndref_ea); + B2N_32(dsi->dsi_gi.vobu_3rdref_ea); + B2N_16(dsi->dsi_gi.vobu_vob_idn); + + /* dsi sml pbi */ + B2N_16(dsi->sml_pbi.category); + B2N_32(dsi->sml_pbi.ilvu_ea); + B2N_32(dsi->sml_pbi.ilvu_sa); + B2N_16(dsi->sml_pbi.size); + B2N_32(dsi->sml_pbi.vob_v_s_s_ptm); + B2N_32(dsi->sml_pbi.vob_v_e_e_ptm); + + /* dsi sml agli */ + for(i = 0; i < 9; i++) { + B2N_32(dsi->sml_agli.data[ i ].address); + B2N_16(dsi->sml_agli.data[ i ].size); + } + + /* dsi vobu sri */ + B2N_32(dsi->vobu_sri.next_video); + for(i = 0; i < 19; i++) + B2N_32(dsi->vobu_sri.fwda[i]); + B2N_32(dsi->vobu_sri.next_vobu); + B2N_32(dsi->vobu_sri.prev_vobu); + for(i = 0; i < 19; i++) + B2N_32(dsi->vobu_sri.bwda[i]); + B2N_32(dsi->vobu_sri.prev_video); + + /* dsi synci */ + for(i = 0; i < 8; i++) + B2N_16(dsi->synci.a_synca[i]); + for(i = 0; i < 32; i++) + B2N_32(dsi->synci.sp_synca[i]); + + + /* Asserts */ + + /* dsi dsi gi */ + assert(dsi->dsi_gi.zero1 == 0); +} + diff --git a/src/dxr3/nav_read.h b/src/dxr3/nav_read.h new file mode 100644 index 000000000..ba4dc4dca --- /dev/null +++ b/src/dxr3/nav_read.h @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2000, 2001 Håkan Hjort <d95hjort@dtek.chalmers.se>. + * + * This program 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. + * + * This program 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 + */ + +#ifndef NAV_READ_H_INCLUDED +#define NAV_READ_H_INCLUDED + +#include "nav_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Reads the PCI packet which begins at buffer into pci. + */ +void nav_read_pci(pci_t *pci, unsigned char *buffer); + +/** + * Reads the DSI packet which begins at buffer into dsi. + */ +void nav_read_dsi(dsi_t *dsi, unsigned char *buffer); + +#ifdef __cplusplus +}; +#endif +#endif /* NAV_READ_H_INCLUDED */ diff --git a/src/dxr3/nav_types.h b/src/dxr3/nav_types.h new file mode 100644 index 000000000..032bdedf7 --- /dev/null +++ b/src/dxr3/nav_types.h @@ -0,0 +1,404 @@ +/** + * Copyright (C) 2000 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * The data structures in this file should represent the layout of the + * pci and dsi packets as they are stored in the stream. Information + * found by reading the source to VOBDUMP is the base for the structure + * and names of these data types. + * + * VOBDUMP: a program for examining DVD .VOB files. + * Copyright 1998, 1999 Eric Smith <eric@brouhaha.com> + * + * VOBDUMP is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. Note that I am not + * granting permission to redistribute or modify VOBDUMP under the terms + * of any later version of the General Public License. + * + * This program is distributed in the hope that it will be useful (or at + * least amusing), 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 + */ + +#ifndef NAV_TYPES_H_INCLUDED +#define NAV_TYPES_H_INCLUDED + +#include <inttypes.h> + +#undef ATTRIBUTE_PACKED +#undef PRAGMA_PACK_BEGIN +#undef PRAGMA_PACK_END + +#if defined(__GNUC__) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +#define ATTRIBUTE_PACKED __attribute__ ((packed)) +#define PRAGMA_PACK 0 +#endif +#endif + +#if !defined(ATTRIBUTE_PACKED) +#define ATTRIBUTE_PACKED +#define PRAGMA_PACK 1 +#endif + + +/* The length including the substream id byte. */ +#define PCI_BYTES 0x3d4 +#define DSI_BYTES 0x3fa + +#define PS2_PCI_SUBSTREAM_ID 0x00 +#define PS2_DSI_SUBSTREAM_ID 0x01 + +/* Remove this */ +#define DSI_START_BYTE 1031 + + +#if PRAGMA_PACK +#pragma pack(1) +#endif + +/** + * DVD Time Information. + */ +typedef struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t frame_u; // The two high bits are the frame rate. +} ATTRIBUTE_PACKED dvd_time_t; + +/** + * Type to store per-command data. + */ +typedef struct { + uint8_t bytes[8]; +} ATTRIBUTE_PACKED vm_cmd_t; + +/** + * User Operations. + */ +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int zero : 7; // 25-31 + unsigned int video_pres_mode_change : 1; // 24 + + unsigned int karaoke_audio_pres_mode_change : 1; // 23 + unsigned int angle_change : 1; // 22 + unsigned int subpic_stream_change : 1; // 21 + unsigned int audio_stream_change : 1; // 20 + unsigned int pause_on : 1; // 19 + unsigned int still_off : 1; // 18 + unsigned int button_select_or_activate : 1; // 17 + unsigned int resume : 1; // 16 + + unsigned int chapter_menu_call : 1; // 15 + unsigned int angle_menu_call : 1; // 14 + unsigned int audio_menu_call : 1; // 13 + unsigned int subpic_menu_call : 1; // 12 + unsigned int root_menu_call : 1; // 11 + unsigned int title_menu_call : 1; // 10 + unsigned int backward_scan : 1; // 9 + unsigned int forward_scan : 1; // 8 + + unsigned int next_pg_search : 1; // 7 + unsigned int prev_or_top_pg_search : 1; // 6 + unsigned int time_or_chapter_search : 1; // 5 + unsigned int go_up : 1; // 4 + unsigned int stop : 1; // 3 + unsigned int title_play : 1; // 2 + unsigned int chapter_search_or_play : 1; // 1 + unsigned int title_or_time_play : 1; // 0 +#else + unsigned int video_pres_mode_change : 1; // 24 + unsigned int zero : 7; // 25-31 + + unsigned int resume : 1; // 16 + unsigned int button_select_or_activate : 1; // 17 + unsigned int still_off : 1; // 18 + unsigned int pause_on : 1; // 19 + unsigned int audio_stream_change : 1; // 20 + unsigned int subpic_stream_change : 1; // 21 + unsigned int angle_change : 1; // 22 + unsigned int karaoke_audio_pres_mode_change : 1; // 23 + + unsigned int forward_scan : 1; // 8 + unsigned int backward_scan : 1; // 9 + unsigned int title_menu_call : 1; // 10 + unsigned int root_menu_call : 1; // 11 + unsigned int subpic_menu_call : 1; // 12 + unsigned int audio_menu_call : 1; // 13 + unsigned int angle_menu_call : 1; // 14 + unsigned int chapter_menu_call : 1; // 15 + + unsigned int title_or_time_play : 1; // 0 + unsigned int chapter_search_or_play : 1; // 1 + unsigned int title_play : 1; // 2 + unsigned int stop : 1; // 3 + unsigned int go_up : 1; // 4 + unsigned int time_or_chapter_search : 1; // 5 + unsigned int prev_or_top_pg_search : 1; // 6 + unsigned int next_pg_search : 1; // 7 +#endif +} ATTRIBUTE_PACKED user_ops_t; + + + +/** + * PCI General Information + */ +typedef struct { + uint32_t nv_pck_lbn; + uint16_t vobu_cat; + uint16_t zero1; + user_ops_t vobu_uop_ctl; + uint32_t vobu_s_ptm; + uint32_t vobu_e_ptm; + uint32_t vobu_se_e_ptm; + dvd_time_t e_eltm; + char vobu_isrc[32]; +} ATTRIBUTE_PACKED pci_gi_t; + +/** + * Non Seamless Angle Information + */ +typedef struct { + uint32_t nsml_agl_dsta[9]; +} ATTRIBUTE_PACKED nsml_agli_t; + +/** + * Highlight General Information + */ +typedef struct { + uint16_t hli_ss; // only low 2 bits + uint32_t hli_s_ptm; + uint32_t hli_e_ptm; + uint32_t btn_se_e_ptm; +#ifdef WORDS_BIGENDIAN + unsigned int zero1 : 2; + unsigned int btngr_ns : 2; + unsigned int zero2 : 1; + unsigned int btngr1_dsp_ty : 3; /* type=1 for Widescreen, type=4 for Pan/Scan */ + unsigned int zero3 : 1; + unsigned int btngr2_dsp_ty : 3; + unsigned int zero4 : 1; + unsigned int btngr3_dsp_ty : 3; +#else + unsigned int btngr1_dsp_ty : 3; + unsigned int zero2 : 1; + unsigned int btngr_ns : 2; + unsigned int zero1 : 2; + unsigned int btngr3_dsp_ty : 3; + unsigned int zero4 : 1; + unsigned int btngr2_dsp_ty : 3; + unsigned int zero3 : 1; +#endif + uint8_t btn_ofn; + uint8_t btn_ns; // only low 6 bits + uint8_t nsl_btn_ns; // only low 6 bits + uint8_t zero5; + uint8_t fosl_btnn; // only low 6 bits + uint8_t foac_btnn; // only low 6 bits +} ATTRIBUTE_PACKED hl_gi_t; + + +/** + * Button Color Information Table + */ +typedef struct { + uint32_t btn_coli[3][2]; +} ATTRIBUTE_PACKED btn_colit_t; + + +/* + btn_coln 11000000 00000000 00000000 00000000 00000000 00000000 + x_start 00111111 11110000 00000000 00000000 00000000 00000000 + zero1 00000000 00001100 00000000 00000000 00000000 00000000 + x_end 00000000 00000011 11111111 00000000 00000000 00000000 + auto_action_mode 00000000 00000000 00000000 11000000 00000000 00000000 + y_start 00000000 00000000 00000000 00111111 11110000 00000000 + zero2 00000000 00000000 00000000 00000000 00001100 00000000 + y_end 00000000 00000000 00000000 00000000 00000011 11111111 + + unsigned int btn_coln : 2; // 0 - m[0]>>6 + unsigned int x_start : 10; // 2 - m[0]<<4 | m[1]>>4 + unsigned int zero1 : 2; // 12 - m[1]>>2 + unsigned int x_end : 10; // 14 - m[1]<<8 | m[2] + + unsigned int auto_action_mode : 2; // 24 - m[3]>>6 + unsigned int y_start : 10; // 26 - m[3]<<4 | m[4]>>4 + unsigned int zero2 : 2; // 36 - m[4]>>2 + unsigned int y_end : 10; // 38 - m[4]<<8 | m[5] + */ + +/** + * Button Information + */ +typedef struct { +#if 0 /* Wierd Sun CC code that does not work */ + unsigned int zero1 : 2; + unsigned int x_start : 10; + unsigned int x_end : 10; + unsigned int y_start : 10; + + unsigned int zero2 : 2; + unsigned int btn_coln : 2; + unsigned int auto_action_mode : 2; + unsigned int y_end : 10; +#endif +#ifdef WORDS_BIGENDIAN + unsigned int btn_coln : 2; + unsigned int x_start : 10; + unsigned int zero1 : 2; + unsigned int x_end : 10; + unsigned int auto_action_mode : 2; + unsigned int y_start : 10; + unsigned int zero2 : 2; + unsigned int y_end : 10; + + unsigned int zero3 : 2; + unsigned int up : 6; + unsigned int zero4 : 2; + unsigned int down : 6; + unsigned int zero5 : 2; + unsigned int left : 6; + unsigned int zero6 : 2; + unsigned int right : 6; +#else + unsigned int x_end : 10; + unsigned int zero1 : 2; + unsigned int x_start : 10; + unsigned int btn_coln : 2; + unsigned int y_end : 10; + unsigned int zero2 : 2; + unsigned int y_start : 10; + unsigned int auto_action_mode : 2; + + unsigned int up : 6; + unsigned int zero3 : 2; + unsigned int down : 6; + unsigned int zero4 : 2; + unsigned int left : 6; + unsigned int zero5 : 2; + unsigned int right : 6; + unsigned int zero6 : 2; +#endif + vm_cmd_t cmd; +} ATTRIBUTE_PACKED btni_t; + +/** + * Highlight Information + */ +typedef struct { + hl_gi_t hl_gi; + btn_colit_t btn_colit; + btni_t btnit[36]; +} ATTRIBUTE_PACKED hli_t; + +/** + * PCI packet + */ +typedef struct { + pci_gi_t pci_gi; + nsml_agli_t nsml_agli; + hli_t hli; + uint8_t zero1[189]; +} ATTRIBUTE_PACKED pci_t; + + + + +/** + * DSI General Information + */ +typedef struct { + uint32_t nv_pck_scr; + uint32_t nv_pck_lbn; + uint32_t vobu_ea; + uint32_t vobu_1stref_ea; + uint32_t vobu_2ndref_ea; + uint32_t vobu_3rdref_ea; + uint16_t vobu_vob_idn; + uint8_t zero1; + uint8_t vobu_c_idn; + dvd_time_t c_eltm; +} ATTRIBUTE_PACKED dsi_gi_t; + +/** + * Seamless Playback Information + */ +typedef struct { + uint16_t category; // category of seamless VOBU + uint32_t ilvu_ea; // end address of interleaved Unit (sectors) + uint32_t ilvu_sa; // start address of next interleaved unit (sectors) + uint16_t size; // size of next interleaved unit (sectors) + uint32_t vob_v_s_s_ptm; /* video start ptm in vob */ + uint32_t vob_v_e_e_ptm; /* video end ptm in vob */ + struct { + uint32_t stp_ptm1; + uint32_t stp_ptm2; + uint32_t gap_len1; + uint32_t gap_len2; + } vob_a[8]; +} ATTRIBUTE_PACKED sml_pbi_t; + +/** + * Seamless Angle Infromation for one angle + */ +typedef struct { + uint32_t address; // Sector offset to next ILVU, high bit is before/after + uint16_t size; // Byte size of the ILVU poited to by address. +} ATTRIBUTE_PACKED sml_agl_data_t; + +/** + * Seamless Angle Infromation + */ +typedef struct { + sml_agl_data_t data[9]; +} ATTRIBUTE_PACKED sml_agli_t; + +/** + * VOBU Search Information + */ +typedef struct { + uint32_t next_video; // Next vobu that contains video + uint32_t fwda[19]; // Forwards, time + uint32_t next_vobu; + uint32_t prev_vobu; + uint32_t bwda[19]; // Backwards, time + uint32_t prev_video; +} ATTRIBUTE_PACKED vobu_sri_t; + +#define SRI_END_OF_CELL 0x3fffffff + +/** + * Synchronous Information + */ +typedef struct { + uint16_t a_synca[8]; // Sector offset to first audio packet for this VOBU + uint32_t sp_synca[32]; // Sector offset to first subpicture packet +} ATTRIBUTE_PACKED synci_t; + +/** + * DSI packet + */ +typedef struct { + dsi_gi_t dsi_gi; + sml_pbi_t sml_pbi; + sml_agli_t sml_agli; + vobu_sri_t vobu_sri; + synci_t synci; + uint8_t zero1[471]; +} ATTRIBUTE_PACKED dsi_t; + + +#if PRAGMA_PACK +#pragma pack() +#endif + +#endif /* NAV_TYPES_H_INCLUDED */ |