summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dxr3/Makefile.am4
-rw-r--r--src/dxr3/bswap.h87
-rw-r--r--src/dxr3/dxr3_decoder.c275
-rw-r--r--src/dxr3/dxr3_video_out.c65
-rw-r--r--src/dxr3/dxr3_video_out.h6
-rw-r--r--src/dxr3/dxr3_vo_core.c4
-rw-r--r--src/dxr3/nav_read.c207
-rw-r--r--src/dxr3/nav_read.h41
-rw-r--r--src/dxr3/nav_types.h404
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 */