summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dxr3/Makefile.am4
-rw-r--r--src/dxr3/bswap.h88
-rw-r--r--src/dxr3/dxr3.h32
-rw-r--r--src/dxr3/dxr3_decode_spu.c711
-rw-r--r--src/dxr3/dxr3_decode_video.c1245
-rw-r--r--src/dxr3/dxr3_scr.c247
-rw-r--r--src/dxr3/dxr3_scr.h37
-rw-r--r--src/dxr3/dxr3_video_out.c460
-rw-r--r--src/dxr3/dxr3_video_out.h162
-rw-r--r--src/dxr3/dxr3_vo_core.c1166
-rw-r--r--src/dxr3/mpeg_encoders.c670
-rw-r--r--src/dxr3/nav_read.c208
-rw-r--r--src/dxr3/nav_read.h42
-rw-r--r--src/dxr3/nav_types.h405
14 files changed, 2346 insertions, 3131 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am
index 5d64ac54b..ae9d535c7 100644
--- a/src/dxr3/Makefile.am
+++ b/src/dxr3/Makefile.am
@@ -16,7 +16,7 @@ endif
lib_LTLIBRARIES = $(dxr3_modules)
-xineplug_decode_dxr3_video_la_SOURCES = dxr3_decode_video.c
+xineplug_decode_dxr3_video_la_SOURCES = dxr3_decode_video.c dxr3_scr.c
xineplug_decode_dxr3_video_la_LDFLAGS = -avoid-version -module
xineplug_decode_dxr3_spu_la_SOURCES = dxr3_decode_spu.c nav_read.c
@@ -28,7 +28,7 @@ xineplug_vo_out_dxr3_la_LIBADD = $(X_LIBS) -lXext
xineplug_vo_out_dxr3_la_LDFLAGS = -avoid-version \
-module $(link_fame) $(link_rte) $(X_LIBS)
-noinst_HEADERS = nav_types.h nav_read.h alphablend.h bswap.h dxr3_video_out.h
+noinst_HEADERS = dxr3.h dxr3_scr.h dxr3_video_out.h nav_types.h nav_read.h alphablend.h bswap.h
debug:
@$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(LINUX_INCLUDE)"
diff --git a/src/dxr3/bswap.h b/src/dxr3/bswap.h
index 23e2863b4..eb45e68e6 100644
--- a/src/dxr3/bswap.h
+++ b/src/dxr3/bswap.h
@@ -1,87 +1 @@
-/**
- * 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 */
+#include "../libspudec/bswap.h"
diff --git a/src/dxr3/dxr3.h b/src/dxr3/dxr3.h
new file mode 100644
index 000000000..f6d3cc2d9
--- /dev/null
+++ b/src/dxr3/dxr3.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: dxr3.h,v 1.1 2002/05/06 11:26:37 jcdutton Exp $
+ */
+
+#include <linux/em8300.h>
+
+/* data for the device name config entry */
+#define CONF_LOOKUP "dxr3.devicename"
+#define CONF_DEFAULT "/dev/em8300-0"
+#define CONF_NAME "Dxr3: Device Name"
+#define CONF_HELP "The device file of the dxr3 mpeg decoder card control device."
+
+/* image format used by dxr3_decoder to tag undecoded mpeg data */
+#define IMGFMT_MPEG (('G'<<24)|('E'<<16)|('P'<<8)|'M')
diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c
index 1bc0e6da3..3b9b78f8a 100644
--- a/src/dxr3/dxr3_decode_spu.c
+++ b/src/dxr3/dxr3_decode_spu.c
@@ -17,47 +17,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_decode_spu.c,v 1.1 2002/05/02 14:33:30 jcdutton Exp $
- *
- * dxr3 video and spu decoder plugin. Accepts the video and spu data
- * from XINE and sends it directly to the corresponding dxr3 devices.
- * Takes precedence over the libmpeg2 and libspudec due to a higher
- * priority.
- * also incorporates an scr plugin for metronom
- *
- * update 7/1/2002 by jcdutton:
- * Updated to work better with the changes done to dvdnav.
- * Subtitles display properly now.
- * TODO: Process NAV packets so that the first
- * menu button appears, and also so that
- * menu buttons disappear when one starts playing the movie.
- * Processing NAV packets will also make "The White Rabbit"
- * work on DXR3 as I currently works on XV.
- *
- * update 25/11/01 by Harm:
- * Major retooling; so much so that I've decided to cvs-tag the dxr3 sources
- * as DXR3_095 before commiting.
- * - major retooling of dxr3_decode_data; Mike Lampard's comments indicate
- * that dxr3_decode_data is called once every 12 frames or so. This seems
- * no longer true; we're in fact called on average more than once per frame.
- * This gives us some interesting possibilities to lead metronom up the garden
- * path (and administer it a healthy beating behind the toolshed ;-).
- * Read the comments for details, but the short version is that we take a
- * look at the scr clock to guestimate when we should call get_frame/draw/free.
- * - renamed update_aspect to parse_mpeg_header.
- * - replaced printing to stderr by stdout, following xine practice and
- * to make it easier to write messages to a log.
- * - replaced 6667 flag with proper define in dxr3_video_out.h
- *
- * The upshot of all this is that sync is a lot better now; I get good
- * a/v sync within a few seconds of playing after start/seek. I also
- * get a lot of "throwing away frame..." messages, especially just
- * after start/seek, but those are relatively harmless. (I guess we
- * call img->draw a tad too often).
- *
- * update 21/12/01 by Harm
- * many revisions, but I've been too lazy to document them here.
- * read the cvs log, that's what it's for anyways.
+ * $Id: dxr3_decode_spu.c,v 1.2 2002/05/06 11:26:37 jcdutton Exp $
+ */
+
+/* dxr3 spu decoder plugin.
+ * Accepts the spu data from xine and sends it directly to the
+ * corresponding dxr3 device. Also handles dvd menu button highlights.
+ * Takes precedence over libspudec due to a higher priority.
*/
@@ -70,462 +36,389 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#include <signal.h>
-#include <linux/soundcard.h>
-#include <linux/em8300.h>
-#include "video_out.h"
#include "xine_internal.h"
+#include "xineutils.h"
#include "buffer.h"
#include "xine-engine/bswap.h"
#include "nav_types.h"
#include "nav_read.h"
+#include "dxr3.h"
-/* for DXR3_VO_UPDATE_FLAG */
-#include "dxr3_video_out.h"
-
-#define LOOKUP_DEV "dxr3.devicename"
-#define DEFAULT_DEV "/dev/em8300"
-static char devname[128];
-static char devnum[3];
-
-/* lots of poohaa about pts things */
#define LOG_PTS 0
-#define LOG_SPU 0
+#define LOG_SPU 0
+#define LOG_BTN 0
-#define MV_COMMAND 0
+#define MAX_SPU_STREAMS 32
-/* the number of frames to pass after an out-of-sync situation
- before locking the stream again */
-#define RESYNC_WINDOW_SIZE 50
-int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn );
+/* plugin initialization function */
+spu_decoder_t *init_spu_decoder_plugin(int iface_version, xine_t *xine);
+
+/* functions required by xine api */
+static char *dxr3_spudec_get_id(void);
+static int dxr3_spudec_can_handle(spu_decoder_t *this_gen, int buf_type);
+static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out);
+static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf);
+static void dxr3_spudec_reset(spu_decoder_t *this_gen);
+static void dxr3_spudec_close(spu_decoder_t *this_gen);
+static void dxr3_spudec_dispose(spu_decoder_t *this_gen);
+
+/* helper functions */
+static int dxr3_present(xine_t *xine);
+static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen);
+static int dxr3_spudec_copy_nav_to_btn(pci_t *nav_pci, int32_t button, int32_t mode, em8300_button_t *btn);
+static void dxr3_swab_clut(int* clut);
+
+/* plugin structures */
+typedef struct dxr3_spu_stream_state_s {
+ uint32_t stream_filter;
+} dxr3_spu_stream_state_t;
+
+typedef struct dxr3_spudec_s {
+ spu_decoder_t spu_decoder;
+ vo_instance_t *vo_out;
+ xine_t *xine;
+
+ char devname[128];
+ char devnum[3];
+ int fd_spu; /* to access the dxr3 spu device */
+
+ dxr3_spu_stream_state_t spu_stream_state[MAX_SPU_STREAMS];
+ int menu; /* are we in a menu? */
+ pci_t pci;
+ uint32_t buttonN; /* currently highlighted button */
+} dxr3_spudec_t;
-/*
- * Second part of the dxr3 plugin: subpicture decoder
- */
-#define MAX_SPU_STREAMS 32
-typedef struct spudec_stream_state_s {
- uint32_t stream_filter;
-} spudec_stream_state_t;
+spu_decoder_t *init_spu_decoder_plugin(int iface_version, xine_t *xine)
+{
+ dxr3_spudec_t *this;
+ char *confstr;
+ int dashpos;
-typedef struct spudec_decoder_s {
- spu_decoder_t spu_decoder;
- spudec_stream_state_t spu_stream_state[MAX_SPU_STREAMS];
- vo_instance_t *vo_out;
- int fd_spu;
- int menu; /* are we in a menu? */
- pci_t pci;
- uint32_t buttonN; /* currently highlighted button */
- int64_t button_vpts; /* time to show the menu enter button */
- xine_t *xine;
-} spudec_decoder_t;
+ if (iface_version != 7) {
+ printf( "dxr3_decode_spu: plugin doesn't support plugin API version %d.\n"
+ "dxr3_decode_spu: this means there's a version mismatch between xine and this "
+ "dxr3_decode_spu: decoder plugin. Installing current plugins should help.\n",
+ iface_version);
+ return NULL;
+ }
+
+ if (!dxr3_present(xine)) return NULL;
+
+ this = (dxr3_spudec_t *)malloc(sizeof(dxr3_spudec_t));
+
+ confstr = xine->config->register_string(xine->config,
+ CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, 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';
+ }
+
+ this->spu_decoder.interface_version = iface_version;
+ this->spu_decoder.get_identifier = dxr3_spudec_get_id;
+ this->spu_decoder.can_handle = dxr3_spudec_can_handle;
+ this->spu_decoder.init = dxr3_spudec_init;
+ this->spu_decoder.decode_data = dxr3_spudec_decode_data;
+ this->spu_decoder.reset = dxr3_spudec_reset;
+ this->spu_decoder.close = dxr3_spudec_close;
+ this->spu_decoder.dispose = dxr3_spudec_dispose;
+ this->spu_decoder.priority = 10;
+
+ this->xine = xine;
+ this->fd_spu = 0;
+ this->menu = 0;
+ this->pci.hli.hl_gi.hli_ss = 0;
+ this->buttonN = 1;
+
+ xine_register_event_listener(xine, dxr3_spudec_event_listener, this);
+
+ return &this->spu_decoder;
+}
-static int dxr3_presence_test( xine_t* xine)
+static char *dxr3_spudec_get_id(void)
{
- int info;
- if (xine && xine->video_driver ) {
- info = xine->video_driver->get_property( xine->video_driver, VO_PROP_VO_TYPE);
- printf("dxr3_presence_test:info=%d\n",info);
- if (info != VO_TYPE_DXR3) {
- return 0;
- }
- }
- return 1;
+ return "dxr3-spudec";
}
-static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type)
+static int dxr3_spudec_can_handle(spu_decoder_t *this_gen, int buf_type)
{
- int type = buf_type & 0xFFFF0000;
- return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT ||
- type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL);
+ int type = buf_type & 0xFFFF0000;
+ return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT ||
+ type == BUF_SPU_NAV || type == BUF_SPU_SUBP_CONTROL);
}
-static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out)
+static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out)
{
- spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
- char tmpstr[100];
- int i;
-
- this->vo_out = vo_out;
-
- /* open spu device */
- snprintf (tmpstr, sizeof(tmpstr), "%s_sp%s", devname, devnum);
- if ((this->fd_spu = open (tmpstr, O_WRONLY)) < 0) {
- printf("dxr3: Failed to open spu device %s (%s)\n",
- tmpstr, strerror(errno));
- return;
- }
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
+ char tmpstr[128];
+ int i;
+
+ this->vo_out = vo_out;
+
+ /* open dxr3 spu device */
+ snprintf(tmpstr, sizeof(tmpstr), "%s_sp%s", this->devname, this->devnum);
+ if ((this->fd_spu = open(tmpstr, O_WRONLY)) < 0) {
+ printf("dxr3_decode_spu: Failed to open spu device %s (%s)\n",
+ tmpstr, strerror(errno));
+ return;
+ }
#if LOG_SPU
- printf ("dxr3_spu: init: SPU_FD = %i\n",this->fd_spu);
+ printf ("dxr3_decode_spu: init: SPU_FD = %i\n",this->fd_spu);
#endif
-
- for (i=0; i < MAX_SPU_STREAMS; i++) /* reset the spu filter for non-dvdnav */
- this->spu_stream_state[i].stream_filter = 1;
+ for (i=0; i < MAX_SPU_STREAMS; i++) /* reset the spu filter for non-dvdnav */
+ this->spu_stream_state[i].stream_filter = 1;
}
-static void swab_clut(int* clut)
+static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf)
{
- int i;
- for (i=0; i<16; i++)
- clut[i] = bswap_32(clut[i]);
-}
-
-static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf)
-{
- spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
- ssize_t written;
- uint32_t stream_id = buf->type & 0x1f ;
-
- if (this->button_vpts &&
- this->xine->metronom->get_current_time(this->xine->metronom) > this->button_vpts) {
- /* we have a scheduled menu enter button and it's time to show it now */
- em8300_button_t button;
- int buttonNr;
- btni_t *button_ptr;
-
- buttonNr = this->buttonN;
-
- if (this->pci.hli.hl_gi.fosl_btnn > 0)
- buttonNr = this->pci.hli.hl_gi.fosl_btnn ;
-
- if ((buttonNr <= 0) || (buttonNr > this->pci.hli.hl_gi.btn_ns)) {
- printf("dxr3_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n", buttonNr);
- buttonNr = 1;
- }
-
- button_ptr = &this->pci.hli.btnit[buttonNr-1];
- button.left = button_ptr->x_start;
- button.top = button_ptr->y_start;
- button.right = button_ptr->x_end;
- button.bottom = button_ptr->y_end;
- button.color = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] >> 16;
- button.contrast = this->pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0] & 0xffff;
-
-#if LOG_SPU
- printf("dxr3_spu: now showing menu enter button %i.\n", buttonNr);
-#endif
- ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &button);
- this->button_vpts = 0;
- this->pci.hli.hl_gi.hli_s_ptm = 0;
- }
-
- if (buf->type == BUF_SPU_CLUT) {
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
+ ssize_t written;
+ uint32_t stream_id = buf->type & 0x1f;
+
+ if (buf->type == BUF_SPU_CLUT) {
#if LOG_SPU
- printf ("dxr3_spu: BUF_SPU_CLUT\n" );
+ printf("dxr3_decode_spu: BUF_SPU_CLUT\n");
#endif
-#if LOG_SPU
- printf ("dxr3_spu: buf clut: SPU_FD = %i\n",this->fd_spu);
+ if (buf->content[0] == 0) /* cheap endianess detection */
+ dxr3_swab_clut((int *)buf->content);
+ if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, buf->content))
+ printf("dxr3_decode_spu: failed to set CLUT (%s)\n", strerror(errno));
+ return;
+ }
+ if(buf->type == BUF_SPU_SUBP_CONTROL) {
+ /* FIXME: is BUF_SPU_SUBP_CONTROL used anymore? */
+ int i;
+ uint32_t *subp_control = (uint32_t *)buf->content;
+
+ for (i = 0; i < MAX_SPU_STREAMS; i++)
+ this->spu_stream_state[i].stream_filter = subp_control[i];
+ return;
+ }
+ if(buf->type == BUF_SPU_NAV) {
+#if LOG_BTN
+ printf("dxr3_decode_spu: got NAV packet\n");
#endif
- if (buf->content[0] == 0) /* cheap endianess detection */
- swab_clut((int*)buf->content);
- if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, buf->content))
- printf("dxr3: failed to set CLUT (%s)\n", strerror(errno));
- return;
- }
- if(buf->type == BUF_SPU_SUBP_CONTROL){
-/***************
- int i;
- uint32_t *subp_control = (uint32_t*) buf->content;
- for (i = 0; i < 32; i++) {
- this->spu_stream_state[i].stream_filter = subp_control[i];
- }
-***************/
- return;
- }
- if(buf->type == BUF_SPU_NAV){
-#if LOG_SPU
- printf("dxr3_spu: Got NAV packet\n");
+ uint8_t *p = buf->content;
+
+ /* just watch out for menus */
+ if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */
+ pci_t pci;
+
+ nav_read_pci(&pci, p + 7);
+#if LOG_BTN
+ printf("dxr3_decode_spu: PCI packet hli_ss is %d\n", pci.hli.hl_gi.hli_ss);
#endif
- uint8_t *p = buf->content;
-
- /* just watch out for menus */
- if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */
- pci_t pci;
-
- nav_read_pci(&pci, p + 7);
-
- if (pci.hli.hl_gi.hli_ss == 1) {
- em8300_button_t btn;
- /* menu ahead, remember pci for later evaluation */
- xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
- if ( (spudec_copy_nav_to_btn(&this->pci, this->buttonN, 0, &btn ) > 0)) {
- if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) {
- printf("dxr3: failed to set spu button (%s)\n",
- strerror(errno));
- }
- }
- }
-
- if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) {
- /* leaving menu */
- xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
- ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL);
- }
- }
- return;
- }
- /* Is this also needed for subpicture? */
- if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
+ if (pci.hli.hl_gi.hli_ss == 1) {
+ em8300_button_t btn;
+
+ /* menu ahead, remember pci for later evaluation */
+ xine_fast_memcpy(&this->pci, &pci, sizeof(pci_t));
+ if ((dxr3_spudec_copy_nav_to_btn(&this->pci, this->buttonN, 0, &btn ) > 0))
+ if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn))
+ printf("dxr3_decode_spu: failed to set spu button (%s)\n",
+ strerror(errno));
+ }
+
+ if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) {
+ /* leaving menu */
+ this->pci.hli.hl_gi.hli_ss = 0;
+ ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL);
+ }
+ }
+ return;
+ }
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
#if LOG_SPU
- printf ("dxr3_spu: Dropping SPU channel %d. Preview data\n", stream_id);
+ printf("dxr3_decode_spu: Dropping SPU channel %d. Preview data\n", stream_id);
#endif
- return;
- }
-
- if ( this->spu_stream_state[stream_id].stream_filter == 0) {
+ return;
+ }
+
+ if (this->spu_stream_state[stream_id].stream_filter == 0) {
#if LOG_SPU
- printf ("dxr3_spu: Dropping SPU channel %d. Stream filtered\n", stream_id);
+ printf("dxr3_decode_spu: Dropping SPU channel %d. Stream filtered\n", stream_id);
#endif
- return;
- }
-/* spu_channel is now set based on whether we are in the menu or not. */
-/* Bit 7 is set if only forced display SPUs should be shown */
- if ( (this->xine->spu_channel & 0x1f) != stream_id ) {
+ return;
+ }
+ if ((this->xine->spu_channel & 0x1f) != stream_id ) {
#if LOG_SPU
- printf ("dxr3_spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id);
+ printf("dxr3_decode_spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id);
#endif
- return;
- }
- if ( (this->menu == 0) && (this->xine->spu_channel & 0x80) ) {
+ 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);
+ printf("dxr3_decode_spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id);
#endif
- return;
- }
-// if (this->xine->spu_channel != stream_id && this->menu!=1 ) return;
- /* Hide any previous button highlights */
-// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL);
- if (buf->pts) {
- int64_t vpts;
- uint32_t vpts32;
-
- vpts = this->xine->metronom->got_spu_packet
- (this->xine->metronom, buf->pts);
-#if LOG_SPU
- printf ("dxr3_spu: pts=%lld vpts=%lld\n", buf->pts, vpts);
+ return;
+ }
+
+ if (buf->pts) {
+ int64_t vpts;
+ uint32_t vpts32;
+
+ vpts = this->xine->metronom->got_spu_packet(
+ this->xine->metronom, buf->pts);
+#if LOG_PTS
+ printf ("dxr3_decode_spu: pts=%lld vpts=%lld\n", buf->pts, vpts);
#endif
- vpts32 = vpts;
- if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32))
- printf("dxr3: spu setpts failed (%s)\n", strerror(errno));
-
- if (buf->pts == this->pci.hli.hl_gi.hli_s_ptm)
- /* schedule the menu enter button for current packet's vpts, so
- that the card has decoded this SPU when we try to show the button */
- this->button_vpts = vpts;
- }
-
-
+ vpts32 = vpts;
+ if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32))
+ printf("dxr3_decode_spu: spu setpts failed (%s)\n", strerror(errno));
+ }
+
#if LOG_SPU
- printf ("dxr3_spu: write: SPU_FD = %i\n",this->fd_spu);
+ printf ("dxr3_decode_spu: write: SPU_FD = %i\n",this->fd_spu);
#endif
- written = write(this->fd_spu, buf->content, buf->size);
- if (written < 0) {
- printf("dxr3: spu device write failed (%s)\n",
- strerror(errno));
- return;
- }
- if (written != buf->size)
- printf("dxr3: Could only write %d of %d spu bytes.\n",
- written, buf->size);
+ written = write(this->fd_spu, buf->content, buf->size);
+ if (written < 0) {
+ printf("dxr3_decode_spu: spu device write failed (%s)\n",
+ strerror(errno));
+ return;
+ }
+ if (written != buf->size)
+ printf("dxr3_decode_spu: Could only write %d of %d spu bytes.\n",
+ written, buf->size);
}
-static void spudec_reset (spu_decoder_t *this_gen)
+static void dxr3_spudec_reset(spu_decoder_t *this_gen)
{
}
-static void spudec_close (spu_decoder_t *this_gen)
+static void dxr3_spudec_close(spu_decoder_t *this_gen)
{
- spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
#if LOG_SPU
- printf ("dxr3_spu: close: SPU_FD = %i\n",this->fd_spu);
+ printf("dxr3_decode_spu: close: SPU_FD = %i\n",this->fd_spu);
#endif
-
- close(this->fd_spu);
- this->fd_spu = 0;
+ close(this->fd_spu);
+ this->fd_spu = 0;
}
-int spudec_copy_nav_to_btn(pci_t* nav_pci, int32_t button, int32_t mode, em8300_button_t* btn ) {
- btni_t *button_ptr;
+static void dxr3_spudec_dispose(spu_decoder_t *this_gen)
+{
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
+
+ xine_remove_event_listener(this->xine, dxr3_spudec_event_listener);
+ free (this);
+}
- /* FIXME: Need to communicate with dvdnav vm to get/set
- "self->vm->state.HL_BTNN_REG" info.
- now done via button events from dvdnav.
- *
- * if ( this->pci.hli.hl_gi.fosl_btnn > 0) {
- * button = this->pci.hli.hl_gi.fosl_btnn ;
- * }
- */
- if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) {
- printf("dxr3_decoder:Unable to select button number %i as it doesn't exist. Forcing button 1\n",
- button);
- button = 1;
- }
- /* There is no point in highlighting an area it the area's colours are no different from the general overlay colours. */
- button_ptr = &nav_pci->hli.btnit[button-1];
- if(button_ptr->btn_coln != 0) {
-#ifdef LOG_BUTTON
- fprintf(stderr, "libspudec: normal button clut\n");
+
+static int dxr3_present(xine_t *xine)
+{
+ int info;
+
+ if (xine && xine->video_driver) {
+ info = xine->video_driver->get_property(xine->video_driver, VO_PROP_VO_TYPE);
+#ifdef LOG_SPU
+ printf("dxr3_decode_spu: dxr3 presence test: info = %d\n", info);
#endif
- btn->color = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] >> 16 );
- btn->contrast = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] );
- /* FIXME:Only the first grouping of buttons are used at the moment */
- btn->left = button_ptr->x_start;
- btn->top = button_ptr->y_start;
- btn->right = button_ptr->x_end;
- btn->bottom = button_ptr->y_end;
- return 1;
- }
- return -1;
+ if (info != VO_TYPE_DXR3)
+ return 0;
+ }
+ return 1;
}
-static void spudec_event_listener (void *this_gen, xine_event_t *event_gen) {
-
- spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
- xine_spu_event_t *event = (xine_spu_event_t *) event_gen;
+static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen)
+{
+ dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen;
+ xine_spu_event_t *event = (xine_spu_event_t *)event_gen;
+
#if LOG_SPU
- printf ("dxr3_spu: event: SPU_FD = %i\n",this->fd_spu);
+ printf ("dxr3_decode_spu: event caught: SPU_FD = %i\n",this->fd_spu);
#endif
switch (event->event.type) {
case XINE_EVENT_SPU_BUTTON:
{
-
spu_button_t *but = event->data;
em8300_button_t btn;
-#if LOG_SPU
- printf ("dxr3_spu: SPU_BUTTON\n");
+#if LOG_BTN
+ printf ("dxr3_decode_spu: got SPU_BUTTON\n");
#endif
-
-// if (!but->show) {
-// ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL);
-// break;
-// }
-
this->buttonN = but->buttonN;
- if ( (but->show > 0) && (spudec_copy_nav_to_btn(&this->pci, this->buttonN, but->show - 1, &btn ) > 0)) {
- if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) {
- printf("dxr3: failed to set spu button (%s)\n",
- strerror(errno));
- }
- }
-#if LOG_SPU
- printf ("dxr3_spu: buttonN = %u\n",but->buttonN);
+ if ((but->show > 0) && (dxr3_spudec_copy_nav_to_btn(
+ &this->pci, this->buttonN, but->show - 1, &btn) > 0))
+ if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn))
+ printf("dxr3_decode_spu: failed to set spu button (%s)\n",
+ strerror(errno));
+#if LOG_BTN
+ printf ("dxr3_decode_spu: buttonN = %u\n",but->buttonN);
#endif
}
break;
-
+
case XINE_EVENT_SPU_CLUT:
{
spudec_clut_table_t *clut = event->data;
#if LOG_SPU
- printf ("dxr3_spu: SPU_CLUT\n");
-#endif
-#if LOG_SPU
- printf ("dxr3_spu: clut: SPU_FD = %i\n",this->fd_spu);
+ printf ("dxr3_spu: got SPU_CLUT\n");
#endif
#ifdef WORDS_BIGENDIAN
- swab_clut(clut->clut);
+ dxr3_swab_clut(clut->clut);
#endif
-
if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, clut->clut))
- printf("dxr3: failed to set CLUT (%s)\n",
- strerror(errno));
- }
- break;
- /* Temporarily use the stream title to find out if we have a menu...
- obsoleted by XINE_EVENT_SPU_FORCEDISPLAY, but we'll keep it 'til
- the next version of dvdnav */
- case XINE_EVENT_UI_SET_TITLE:
- {
- if(strstr(event->data,"Menu"))
- this->menu=1;
- else
- this->menu=0;
+ printf("dxr3_decode_spu: failed to set CLUT (%s)\n",
+ strerror(errno));
}
break;
case XINE_EVENT_SPU_FORCEDISPLAY:
{
- (int*)this->menu=event->data;
+ this->menu = (int)event->data;
}
break;
- default:
- {
- }
-
}
}
-static char *spudec_get_id(void)
+static int dxr3_spudec_copy_nav_to_btn(pci_t *nav_pci, int32_t button, int32_t mode, em8300_button_t *btn)
{
- return "dxr3-spudec";
-}
-
-static void spudec_dispose (spu_decoder_t *this_gen) {
- spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
-
- xine_remove_event_listener (this->xine, spudec_event_listener);
-
- free (this);
+ btni_t *button_ptr;
+
+ /* FIXME: Need to communicate with dvdnav vm to get/set
+ * "self->vm->state.HL_BTNN_REG" info.
+ * now done via button events from dvdnav.
+ *
+ * if ( this->pci.hli.hl_gi.fosl_btnn > 0) {
+ * button = this->pci.hli.hl_gi.fosl_btnn ;
+ * }
+ */
+
+ if ((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) {
+ printf("dxr3_decode_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n",
+ button);
+ button = 1;
+ }
+
+ button_ptr = &nav_pci->hli.btnit[button-1];
+ if(button_ptr->btn_coln != 0) {
+#if LOG_BTN
+ fprintf(stderr, "dxr3_decode_spu: normal button clut, mode %d\n", mode);
+#endif
+ btn->color = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] >> 16);
+ btn->contrast = (nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode]);
+ /* FIXME: Only the first grouping of buttons are used at the moment */
+ btn->left = button_ptr->x_start;
+ btn->top = button_ptr->y_start;
+ btn->right = button_ptr->x_end;
+ btn->bottom = button_ptr->y_end;
+ return 1;
+ }
+ return -1;
}
-spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine)
+static void dxr3_swab_clut(int *clut)
{
- spudec_decoder_t *this;
- config_values_t *cfg;
- char *tmpstr;
- int dashpos;
- int result;
-
- if (iface_version != 7) {
- printf( "dxr3_decode_spu: plugin doesn't support plugin API version %d.\n"
- "dxr3_decode_spu: this means there's a version mismatch between xine and this "
- "dxr3_decode_spu: decoder plugin.\nInstalling current plugins should help.\n",
- iface_version);
- return NULL;
- }
-
- cfg = xine->config;
- tmpstr = cfg->register_string (cfg, LOOKUP_DEV, DEFAULT_DEV, NULL,NULL,NULL,NULL);
- strncpy(devname, tmpstr, 128);
- devname[127] = '\0';
- dashpos = strlen(devname) - 2; /* the dash in the new device naming scheme would be here */
- if (devname[dashpos] == '-') {
- /* use new device naming scheme with trailing number */
- strncpy(devnum, &devname[dashpos], 3);
- devname[dashpos] = '\0';
- } else {
- /* use old device naming scheme without trailing number */
- /* FIXME: remove this when everyone uses em8300 >=0.12.0 */
- devnum[0] = '\0';
- }
-
- result = dxr3_presence_test ( xine );
- if (!result) {
- return NULL;
- }
-
- this = (spudec_decoder_t *) malloc (sizeof (spudec_decoder_t));
-
- this->spu_decoder.interface_version = iface_version;
- this->spu_decoder.can_handle = spudec_can_handle;
- this->spu_decoder.init = spudec_init;
- this->spu_decoder.decode_data = spudec_decode_data;
- this->spu_decoder.reset = spudec_reset;
- this->spu_decoder.close = spudec_close;
- this->spu_decoder.get_identifier = spudec_get_id;
- this->spu_decoder.dispose = spudec_dispose;
- this->spu_decoder.priority = 10;
- this->xine = xine;
- this->menu = 0;
- this->fd_spu = 0;
- this->pci.hli.hl_gi.hli_ss = 0;
- this->pci.hli.hl_gi.hli_s_ptm = 0;
- this->buttonN = 1;
- this->button_vpts = 0;
-
- xine_register_event_listener(xine, spudec_event_listener, this);
-
- return (spu_decoder_t *) this;
+ int i;
+ for (i=0; i<16; i++)
+ clut[i] = bswap_32(clut[i]);
}
diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c
index 9e2fbcf1a..cb6bbfdb7 100644
--- a/src/dxr3/dxr3_decode_video.c
+++ b/src/dxr3/dxr3_decode_video.c
@@ -17,52 +17,17 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_decode_video.c,v 1.1 2002/05/02 14:33:30 jcdutton Exp $
- *
- * dxr3 video and spu decoder plugin. Accepts the video and spu data
- * from XINE and sends it directly to the corresponding dxr3 devices.
- * Takes precedence over the libmpeg2 and libspudec due to a higher
- * priority.
- * also incorporates an scr plugin for metronom
- *
- * update 7/1/2002 by jcdutton:
- * Updated to work better with the changes done to dvdnav.
- * Subtitles display properly now.
- * TODO: Process NAV packets so that the first
- * menu button appears, and also so that
- * menu buttons disappear when one starts playing the movie.
- * Processing NAV packets will also make "The White Rabbit"
- * work on DXR3 as I currently works on XV.
- *
- * update 25/11/01 by Harm:
- * Major retooling; so much so that I've decided to cvs-tag the dxr3 sources
- * as DXR3_095 before commiting.
- * - major retooling of dxr3_decode_data; Mike Lampard's comments indicate
- * that dxr3_decode_data is called once every 12 frames or so. This seems
- * no longer true; we're in fact called on average more than once per frame.
- * This gives us some interesting possibilities to lead metronom up the garden
- * path (and administer it a healthy beating behind the toolshed ;-).
- * Read the comments for details, but the short version is that we take a
- * look at the scr clock to guestimate when we should call get_frame/draw/free.
- * - renamed update_aspect to parse_mpeg_header.
- * - replaced printing to stderr by stdout, following xine practice and
- * to make it easier to write messages to a log.
- * - replaced 6667 flag with proper define in dxr3_video_out.h
- *
- * The upshot of all this is that sync is a lot better now; I get good
- * a/v sync within a few seconds of playing after start/seek. I also
- * get a lot of "throwing away frame..." messages, especially just
- * after start/seek, but those are relatively harmless. (I guess we
- * call img->draw a tad too often).
- *
- * update 21/12/01 by Harm
- * many revisions, but I've been too lazy to document them here.
- * read the cvs log, that's what it's for anyways.
+ * $Id: dxr3_decode_video.c,v 1.2 2002/05/06 11:26:37 jcdutton Exp $
+ */
+
+/* dxr3 video decoder plugin.
+ * Accepts the video data from xine and sends it directly to the
+ * corresponding dxr3 device. Takes precedence over the libmpeg2
+ * due to a higher priority.
*/
#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -70,777 +35,553 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#include <signal.h>
-#include <linux/soundcard.h>
-#include <linux/em8300.h>
-#include "video_out.h"
#include "xine_internal.h"
#include "buffer.h"
-#include "xine-engine/bswap.h"
-#include "nav_types.h"
-#include "nav_read.h"
+#include "dxr3_scr.h"
+#include "dxr3.h"
-/* for DXR3_VO_UPDATE_FLAG */
-#include "dxr3_video_out.h"
-
-#define LOOKUP_DEV "dxr3.devicename"
-#define DEFAULT_DEV "/dev/em8300"
-static char devname[128];
-static char devnum[3];
-
-/* lots of poohaa about pts things */
+#define LOG_VID 1
#define LOG_PTS 0
-#define LOG_SPU 0
-
-#define MV_COMMAND 0
/* the number of frames to pass after an out-of-sync situation
before locking the stream again */
#define RESYNC_WINDOW_SIZE 50
+/* we adjust vpts_offset in metronom, when skip_count reaches this value */
+#define SKIP_TOLERANCE 200
-typedef struct dxr3_decoder_s {
- video_decoder_t video_decoder;
- vo_instance_t *video_out;
- config_values_t *config;
- metronom_t *metronom;
-
- int fd_control;
- int fd_video;
- int64_t last_pts;
- scr_plugin_t *scr;
- int scr_prio;
- int width;
- int height;
- int aspect;
- int frame_rate_code;
- int repeat_first_field;
- /* 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 */
- int sync_retry;
- int enhanced_mode;
- int resync_window;
- int have_header_info;
- int in_buffer_fill;
- pthread_t decoder_thread; /* reference to self */
-} dxr3_decoder_t;
-
-static int dxr3_presence_test( xine_t* xine)
-{
- int info;
- if (xine && xine->video_driver ) {
- info = xine->video_driver->get_property( xine->video_driver, VO_PROP_VO_TYPE);
- printf("dxr3_presence_test:info=%d\n",info);
- if (info != VO_TYPE_DXR3) {
- return 0;
- }
- }
- return 1;
-}
-
-
-/* *** dxr3_mvcommand ***
- Changes the dxr3 playmode. Possible playmodes (currently) are
- 0 - Stop
- 2 - Pause
- 3 - Start playback
- 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
- 0x11 - Flush the onboard buffer???????
- 0x10 - as above???
-*/
-static int dxr3_mvcommand(int fd_control, int command) {
- em8300_register_t regs;
- regs.microcode_register=1; /* Yes, this is a MC Reg */
- regs.reg = MV_COMMAND;
- regs.val=command;
-
- return (ioctl(fd_control, EM8300_IOCTL_WRITEREG, &regs));
-}
-
-typedef struct dxr3scr_s {
- scr_plugin_t scr;
- int fd_control;
- int priority;
- 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 */
- pthread_mutex_t mutex;
-} dxr3scr_t;
-
-static int dxr3scr_get_priority (scr_plugin_t *scr) {
- dxr3scr_t *self = (dxr3scr_t*) scr;
- return self->priority;
-}
-
-
-/* *** dxr3scr_set_speed ***
- sets the speed and playmode of the dxr3. if FFWD is requested
- the function changes the speed of the onboard clock, and sets
- the playmode to SCAN (mv_command 4).
-*/
-int scanning_mode=0;
-static int dxr3scr_set_speed (scr_plugin_t *scr, int speed) {
- dxr3scr_t *self = (dxr3scr_t*) scr;
- uint32_t em_speed;
- int playmode;
-
- switch(speed){
- case SPEED_PAUSE:
- em_speed = 0;
- playmode=MVCOMMAND_PAUSE;
- break;
- case SPEED_SLOW_4:
- em_speed = 0x900/4;
- playmode=MVCOMMAND_START;
- break;
- case SPEED_SLOW_2:
- em_speed = 0x900/2;
- playmode=MVCOMMAND_START;
- break;
- case SPEED_NORMAL:
- em_speed = 0x900;
- playmode=MVCOMMAND_SYNC;
- break;
- case SPEED_FAST_2:
- em_speed = 0x900*2;
- playmode=MVCOMMAND_START;
- break;
- case SPEED_FAST_4:
- em_speed = 0x900*4;
- playmode=MVCOMMAND_START;
- break;
- default:
- em_speed = 0;
- playmode = MVCOMMAND_PAUSE;
- }
-
- if (dxr3_mvcommand(self->fd_control, playmode))
- printf("dxr3scr: failed to playmode (%s)\n", strerror(errno));
-
- if(em_speed>0x900)
- scanning_mode=1;
- else
- scanning_mode=0;
-
- if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SETSPEED, &em_speed))
- printf("dxr3scr: failed to set speed (%s)\n", strerror(errno));
-
- return 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
- _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 cpts32;
- int32_t offset32;
-
- pthread_mutex_lock(&self->mutex);
- if (ioctl(self->fd_control, EM8300_IOCTL_SCR_GET, &cpts32))
- printf("dxr3scr: adjust get failed (%s)\n", strerror(errno));
- self->last_pts = cpts32;
- self->offset = vpts - ((int64_t)cpts32 << 1);
- offset32 = self->offset / 4;
- /* kernel driver ignores diffs < 7200, so abs(offset32) 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->last_pts = vpts32;
- self->offset = vpts - ((int64_t)vpts32 << 1);
- }
- pthread_mutex_unlock(&self->mutex);
-}
+/* offset for mpeg header parsing */
+#define HEADER_OFFSET 0
-/* *** dxr3scr_start ***
- sets the dxr3 onboard system reference clock to match that handed to
- it in start_vpts. also sets the speed of the clock to 0x900 - which
- is normal speed.
-*/
-static void dxr3scr_start (scr_plugin_t *scr, int64_t start_vpts) {
- dxr3scr_t *self = (dxr3scr_t*) scr;
- uint32_t vpts32 = start_vpts >> 1;
- pthread_mutex_lock(&self->mutex);
- self->last_pts = vpts32;
- self->offset = start_vpts - ((int64_t)vpts32 << 1);
- if (ioctl(self->fd_control, EM8300_IOCTL_SCR_SET, &vpts32))
- printf("dxr3scr: start failed (%s)\n", strerror(errno));
- /* mis-use vpts32 */
- vpts32 = 0x900;
- ioctl(self->fd_control, EM8300_IOCTL_SCR_SETSPEED, &vpts32);
- pthread_mutex_unlock(&self->mutex);
-}
+/* plugin initialization function */
+video_decoder_t *init_video_decoder_plugin(int iface_version, xine_t *xine);
+/* functions required by xine api */
+static char *dxr3_get_id(void);
+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);
+static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf);
+static void dxr3_flush(video_decoder_t *this_gen);
+static void dxr3_reset(video_decoder_t *this_gen);
+static void dxr3_close(video_decoder_t *this_gen);
+static void dxr3_dispose(video_decoder_t *this_gen);
-/* *** dxr3_get_current ***
- returns the current SCR value as indicated by the hardware clock
- on the dxr3 - apparently only called when the dxr3_scr plugin is
- master..
-*/
-static int64_t dxr3scr_get_current (scr_plugin_t *scr) {
- dxr3scr_t *self = (dxr3scr_t*) scr;
- uint32_t pts;
- int64_t current;
+/* plugin structure */
+typedef struct dxr3_decoder_s {
+ video_decoder_t video_decoder;
+ vo_instance_t *video_out;
+ dxr3_scr_t *scr;
+ xine_t *xine;
+
+ char devname[128];
+ char devnum[3];
+ int fd_control;
+ int fd_video; /* to access the dxr3 devices */
+
+ int have_header_info;
+ int width;
+ int height;
+ int aspect;
+ int frame_rate_code;
+ int repeat_first_field; /* mpeg stream header data */
+
+ int sync_every_frame;
+ int sync_retry;
+ int enhanced_mode;
+ int resync_window;
+ int skip_count; /* syncing parameters */
+#if LOG_PTS
+ int64_t last_pts;
+#endif
+} dxr3_decoder_t;
- pthread_mutex_lock(&self->mutex);
- if (ioctl(self->fd_control, EM8300_IOCTL_SCR_GET, &pts))
- printf("dxr3scr: get current failed (%s)\n", strerror(errno));
- /* FIXME: The pts value read from the card sometimes drops to zero for
- unknown reasons. We catch this here, but we should better find out, why. */
- if (pts == 0) pts = self->last_pts;
- if (pts < self->last_pts) /* wrap around detected, compensate with offset */
- self->offset += (int64_t)1 << 33;
- self->last_pts = pts;
- current = ((int64_t)pts << 1) + self->offset;
- pthread_mutex_unlock(&self->mutex);
+/* helper functions */
+static int dxr3_present(xine_t *xine);
+static int dxr3_mvcommand(int fd_control, int command);
+static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t *buffer);
+static int get_duration(int framecode, int repeat_first_field);
+static void dxr3_update_priority(void *this_gen, cfg_entry_t *entry);
+static void dxr3_update_sync_mode(void *this_gen, cfg_entry_t *entry);
+static void dxr3_update_enhanced_mode(void *this_gen, cfg_entry_t *entry);
- return current;
-}
- /* *** dxr3scr_exit ***
- clean up for exit
- */
-static void dxr3scr_exit (scr_plugin_t *scr) {
- dxr3scr_t *self = (dxr3scr_t*) scr;
- pthread_mutex_destroy(&self->mutex);
- free (self);
+video_decoder_t *init_video_decoder_plugin(int iface_version, xine_t *xine)
+{
+ dxr3_decoder_t *this;
+ config_values_t *cfg;
+ char *tmpstr;
+ int dashpos;
+
+ if (iface_version != 8) {
+ printf( "dxr3_decode_video: plugin doesn't support plugin API version %d.\n"
+ "dxr3_decode_video: this means there's a version mismatch between xine and this\n"
+ "dxr3_decode_video: decoder plugin. Installing current plugins should help.\n",
+ iface_version);
+ return NULL;
+ }
+
+ if (!dxr3_present(xine)) return NULL;
+
+ this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t));
+
+ cfg = xine->config;
+ tmpstr = cfg->register_string(cfg, CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, NULL, NULL);
+ strncpy(this->devname, tmpstr, 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';
+ }
+
+ this->video_decoder.interface_version = iface_version;
+ this->video_decoder.get_identifier = dxr3_get_id;
+ this->video_decoder.can_handle = dxr3_can_handle;
+ this->video_decoder.init = dxr3_init;
+ this->video_decoder.decode_data = dxr3_decode_data;
+ this->video_decoder.flush = dxr3_flush;
+ this->video_decoder.reset = dxr3_reset;
+ this->video_decoder.close = dxr3_close;
+ this->video_decoder.dispose = dxr3_dispose;
+ this->video_decoder.priority = cfg->register_num(cfg,
+ "dxr3.decoder_priority", 10, "Dxr3: video decoder priority",
+ "Decoder priorities greater 5 enable hardware decoding, 0 disables it.",
+ dxr3_update_priority, this);
+
+ this->scr = NULL;
+ this->xine = xine;
+
+ this->have_header_info = 0;
+ this->repeat_first_field = 0;
+
+ this->sync_every_frame = cfg->register_bool(cfg,
+ "dxr3.sync_every_frame", 0, "Try to sync video every frame",
+ "This is relevant for progressive video only (most PAL films).",
+ dxr3_update_sync_mode, this);
+ this->sync_retry = 0;
+ this->enhanced_mode = cfg->register_bool(cfg,
+ "dxr3.alt_play_mode", 1, "Use alternate Play mode",
+ "Enabling this option will utilise a smoother play mode.",
+ dxr3_update_enhanced_mode, this);
+
+ return &this->video_decoder;
}
-/* *** dxr3scr_init ***
- initialise the SCR plugin
-*/
-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));
-
- self->scr.interface_version = 2;
- self->scr.get_priority = dxr3scr_get_priority;
- self->scr.set_speed = dxr3scr_set_speed;
- self->scr.adjust = dxr3scr_adjust;
- self->scr.start = dxr3scr_start;
- self->scr.get_current = dxr3scr_get_current;
- self->scr.exit = dxr3scr_exit;
-
- self->offset = 0;
- self->last_pts = 0;
- pthread_mutex_init(&self->mutex, NULL);
-
- 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",
- tmpstr, strerror(errno));
- return NULL;
- }
-
- self->priority = dxr3->scr_prio;
-
- printf("dxr3scr_init: init complete\n");
- return &self->scr;
+static char *dxr3_get_id(void)
+{
+ return "dxr3-mpeg2";
}
-static int dxr3_can_handle (video_decoder_t *this_gen, int buf_type)
+static int dxr3_can_handle(video_decoder_t *this_gen, int buf_type)
{
- buf_type &= 0xFFFF0000;
- return (buf_type == BUF_VIDEO_MPEG);
+ buf_type &= 0xFFFF0000;
+ return (buf_type == BUF_VIDEO_MPEG);
}
-static void dxr3_init (video_decoder_t *this_gen, vo_instance_t *video_out)
+static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out)
{
- dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen;
- metronom_t *metronom = this->metronom;
- char tmpstr[128];
- int64_t cur_offset;
-
- 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 (tmpstr, O_WRONLY)) < 0) {
- printf("dxr3: Failed to open control device %s (%s)\n",
- tmpstr, strerror(errno));
- return;
- }
-
- video_out->open(video_out);
- this->video_out = video_out;
-
- this->last_pts = metronom->get_current_time(metronom);
- this->decoder_thread = pthread_self();
-
- this->resync_window = 0;
-
- cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET);
- metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset - 21600);
- /* a note on the 21600: this seems to be a necessary offset,
- maybe the dxr3 needs some internal time, however it improves sync a lot */
+ dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
+ metronom_t *metronom = this->xine->metronom;
+ char tmpstr[128];
+ int64_t cur_offset;
+
+ snprintf(tmpstr, sizeof(tmpstr), "%s%s", this->devname, this->devnum);
+#if LOG_VID
+ printf("dxr3_decode_video: Entering video init, devname=%s.\n",tmpstr);
+#endif
+
+ /* open later, because dxr3_video_out might have it open until we request a frame */
+ this->fd_video = -1;
+
+ if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) {
+ printf("dxr3_decode_video: Failed to open control device %s (%s)\n",
+ tmpstr, strerror(errno));
+ return;
+ }
+
+ video_out->open(video_out);
+ this->video_out = video_out;
+
+ this->resync_window = 0;
+ this->skip_count = 0;
+
+ cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET);
+ metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset - 21600);
+ /* a note on the 21600: this seems to be a necessary offset,
+ maybe the dxr3 needs some internal time, however it improves sync a lot */
+
+#if LOG_PTS
+ this->last_vpts = metronom->get_current_time(metronom);
+#endif
}
-
-/* *** parse_mpeg_header ***
- Does a partial parse of the mpeg buffer, extracting information such as
- frame width & height, aspect ratio, and framerate, and sends it to the
- video_out plugin via get_frame
-*/
-#define HEADER_OFFSET 0
-static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer)
+static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf)
{
- /* framerate code... needed for metronom */
- this->frame_rate_code = buffer[HEADER_OFFSET+3] & 15;
-
- /* grab video resolution and aspect ratio from the stream */
- this->height = (buffer[HEADER_OFFSET+0] << 16) |
- (buffer[HEADER_OFFSET+1] << 8) |
- buffer[HEADER_OFFSET+2];
- this->width = ((this->height >> 12) + 15) & ~15;
- this->height = ((this->height & 0xfff) + 15) & ~15;
- this->aspect = buffer[HEADER_OFFSET+3] >> 4;
-
- this->have_header_info = 1;
+ dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
+ ssize_t written;
+ int64_t vpts;
+ int i, duration, skip;
+ vo_frame_t *img;
+ uint8_t *buffer, byte;
+ uint32_t shift;
+
+ vpts = 0;
+
+ /* parse frames in the buffer handed in, evaluate headers,
+ * send frames to video_out and handle some syncing
+ */
+ buffer = buf->content;
+ shift = 0xffffff00;
+ for (i=0; i<buf->size; i++) {
+ byte = *buffer++;
+ if (shift != 0x00000100) {
+ shift = (shift | byte) << 8;
+ continue;
+ }
+ /* header code of some kind found */
+ shift = 0xffffff00;
+ if (byte == 0xb3) {
+ /* sequence data */
+ parse_mpeg_header(this, buffer);
+ continue;
+ }
+ if (byte == 0xb5) {
+ /* extension data */
+ if ((buffer[0] & 0xf0) == 0x80)
+ this->repeat_first_field = (buffer[3] >> 1) & 1;
+ /* check if we can keep syncing */
+ if (this->repeat_first_field && this->sync_retry) /* reset counter */
+ this->sync_retry = 500;
+ if (this->repeat_first_field && this->sync_every_frame) {
+#if LOG_VID
+ printf("dxr3: non-progressive video detected. "
+ "disabling sync_every_frame.\n");
+#endif
+ this->sync_every_frame = 0;
+ this->sync_retry = 500; /* see you later */
+ }
+ continue;
+ }
+ if (byte != 0x00) /* Don't care what it is. It's not a new frame */
+ continue;
+ /* we have a code for a new frame */
+ if (!this->have_header_info) /* this->width et al may still be undefined */
+ continue;
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW)
+ continue;
+
+ duration = get_duration(this->frame_rate_code, this->repeat_first_field);
+ /* pretend like we have decoded a frame */
+ img = this->video_out->get_frame (this->video_out,
+ this->width, this->height, this->aspect,
+ IMGFMT_MPEG, VO_BOTH_FIELDS);
+ img->pts = buf->pts;
+ img->bad_frame = 0;
+ img->duration = duration;
+
+ skip = img->draw(img);
+ if (skip <= 0) { /* don't skip */
+ vpts = img->vpts; /* copy so we can free img */
+
+ if (this->skip_count) this->skip_count--;
+
+ if (this->resync_window == 0 && this->scr && this->enhanced_mode &&
+ !this->scr->scanning) {
+ /* we are in sync, so we can lock the stream now */
+#if LOG_VID
+ printf("dxr3_decode_video: in sync, stream locked\n");
+#endif
+ dxr3_mvcommand(this->fd_control, MVCOMMAND_SYNC);
+ this->resync_window = -RESYNC_WINDOW_SIZE;
+ }
+ if (this->resync_window != 0 && this->resync_window > -RESYNC_WINDOW_SIZE)
+ this->resync_window--;
+ }
+ else { /* metronom says skip, so don't set vpts */
+#if LOG_VID
+ printf("dxr3_decode_video: %d frames to skip\n", skip);
+#endif
+ vpts = 0;
+
+ this->skip_count += skip;
+ if (this->skip_count > SKIP_TOLERANCE) {
+ /* we have had enough skipping messages now, let's react */
+ this->xine->metronom->set_option(this->xine->metronom,
+ METRONOM_ADJ_VPTS_OFFSET, skip * (int64_t)img->duration / 2);
+ this->skip_count = 0;
+ this->resync_window = 0;
+ }
+
+ if (this->scr && this->scr->scanning) this->resync_window = 0;
+ if (this->resync_window == 0 && this->scr && this->enhanced_mode &&
+ !this->scr->scanning) {
+ /* switch off sync mode in the card to allow resyncing */
+#if LOG_VID
+ printf("dxr3_decode_video: out of sync, allowing stream resync\n");
+#endif
+ dxr3_mvcommand(this->fd_control, MVCOMMAND_START);
+ this->resync_window = RESYNC_WINDOW_SIZE;
+ }
+ if (this->resync_window != 0 && this->resync_window < RESYNC_WINDOW_SIZE)
+ this->resync_window++;
+ }
+ img->free(img);
+#if LOG_PTS
+ this->last_vpts += img->duration; /* predict vpts */
+#endif
+ /* if sync_every_frame was disabled, decrease the counter
+ * for a retry
+ * (it might be due to crappy studio logos and stuff
+ * so we should give the main movie a chance)
+ */
+ if (this->sync_retry) {
+ if (!--this->sync_retry) {
+#if LOG_VID
+ printf("dxr3_decode_video: retrying sync_every_frame");
+#endif
+ this->sync_every_frame = 1;
+ }
+ }
+ }
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW) return;
+
+ /* ensure video device is open
+ * (we open it late because on occasion the dxr3 video out driver
+ * wants to open it)
+ */
+ if (this->fd_video < 0) {
+ char tmpstr[128];
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum);
+ if ((this->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK)) < 0) {
+ printf("dxr3_decode_video: Failed to open video device %s (%s)\n",
+ tmpstr, strerror(errno));
+ return;
+ }
+ }
+
+ /* We may want to issue a SETPTS, so make sure the scr plugin
+ * is running and registered. Unfortuantely wa cannot do this
+ * earlier, because the dxr3's internal scr gets confused
+ * when started with a closed video device. Maybe this is a
+ * driver bug and gets fixed somewhen. FIXME: We might then
+ * want to move this code to dxr3_init.
+ */
+ if (!this->scr) {
+ int64_t time;
+
+ time = this->xine->metronom->get_current_time(
+ this->xine->metronom);
+
+ this->scr = dxr3_scr_init(this->xine);
+ this->scr->scr_plugin.start(&this->scr->scr_plugin, time);
+ this->xine->metronom->register_scr(
+ this->xine->metronom, &this->scr->scr_plugin);
+ if (this->xine->metronom->scr_master == &this->scr->scr_plugin)
+#if LOG_VID
+ printf("dxr3_decode_video: dxr3_scr plugin is master\n");
+#endif
+ else
+#if LOG_VID
+ printf("dxr3_decode_video: dxr3scr plugin is NOT master\n");
+#endif
+ }
+
+ /* update the pts timestamp in the card, which tags the data we write to it */
+ if (vpts) {
+ int64_t delay;
+
+ delay = vpts - this->xine->metronom->get_current_time(
+ this->xine->metronom);
+#if LOG_PTS
+ printf("dxr3_decode_video: SETPTS got %lld expected = %lld (delta %lld) delay = %lld\n",
+ vpts, this->last_vpts, vpts - this->last_vpts, delay);
+ this->last_vpts = vpts;
+#endif
+ /* SETPTS only if less then one second in the future and
+ * 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, &vpts32))
+ printf("dxr3_decode_video: set video pts failed (%s)\n",
+ strerror(errno));
+ }
+ if (delay >= 90000) /* frame more than 1 sec ahead */
+ printf("dxr3_decode_video: WARNING: vpts %lld is %.02f seconds ahead of time!\n",
+ vpts, delay/90000.0);
+ if (delay < 0)
+ printf("dxr3_decode_video: WARNING: overdue frame.\n");
+ }
+#if LOG_PTS
+ else if (buf->pts) {
+ printf("dxr3_decode_video: skip buf->pts = %lld (no vpts) last_vpts = %lld\n",
+ buf->pts, this->last_vpts);
+ }
+#endif
+
+ /* now write the content to the dxr3 mpeg device and, in a dramatic
+ * break with open source tradition, check the return value
+ */
+ written = write(this->fd_video, buf->content, buf->size);
+ if (written < 0) {
+ if (errno == EAGAIN) {
+ printf("dxr3_decode_video: write to device would block. flushing\n");
+ dxr3_flush(this_gen);
+ } else {
+ printf("dxr3_decode_video: video device write failed (%s)\n",
+ strerror(errno));
+ }
+ return;
+ }
+ if (written != buf->size)
+ printf("dxr3_decode_video: Could only write %d of %d video bytes.\n",
+ written, buf->size);
}
-static int get_duration(int framecode, int repeat_first_field)
+static void dxr3_flush(video_decoder_t *this_gen)
{
- int duration;
- switch (framecode){
- case 1: /* 23.976 */
- duration=3913;
- break;
- case 2: /* 24.000 */
- duration=3750;
- break;
- case 3: /* 25.000 */
- duration=repeat_first_field ? 5400 : 3600;
- /*duration=3600;*/
- break;
- case 4: /* 29.970 */
- duration=repeat_first_field ? 4505 : 3003;
- /*duration=3003;*/
- break;
- case 5: /* 30.000 */
- duration=3000;
- break;
- case 6: /* 50.000 */
- duration=1800;
- break;
- case 7: /* 59.940 */
- duration=1525;
- break;
- case 8: /* 60.000 */
- duration=1509;
- break;
- default:
- printf("dxr3: warning: unknown frame rate code %d: using PAL\n", framecode);
- duration=3600; /* PAL 25fps */
- break;
- }
- return duration;
+ dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
+
+ if (this->fd_video >= 0) fsync(this->fd_video);
}
static void dxr3_reset(video_decoder_t *this_gen)
{
-/* dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen; */
}
-/* *** dxr3_flush ***
- flush the dxr3's onboard buffers - but I'm not sure that this is
- doing that - more testing is required.
-*/
-static void dxr3_flush (video_decoder_t *this_gen)
+static void dxr3_close(video_decoder_t *this_gen)
{
- dxr3_decoder_t *this = (dxr3_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;*/
- if (this->fd_video >= 0)
- fsync(this->fd_video);
+ dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen;
+ metronom_t *metronom = this->xine->metronom;
+ int64_t cur_offset;
+
+ if (this->scr) {
+ metronom->unregister_scr(metronom, &this->scr->scr_plugin);
+ this->scr->scr_plugin.exit(&this->scr->scr_plugin);
+ this->scr = NULL;
+ }
+
+ /* revert av_offset change done in dxr3_init */
+ cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET);
+ metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset + 21600);
+
+ if (this->fd_video >= 0) close(this->fd_video);
+ this->fd_video = -1;
+
+ this->video_out->close(this->video_out);
+
+ this->have_header_info = 0;
}
-
-static void dxr3_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
+static void dxr3_dispose(video_decoder_t *this_gen)
{
- dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen;
- ssize_t written;
- int64_t vpts;
- int i, duration, skip;
- vo_frame_t *img;
- uint8_t *buffer, byte;
- uint32_t shift;
-
- if (buf->decoder_flags & BUF_FLAG_PREVIEW) return;
-
- vpts = 0;
-
- /* count the number of frame codes in this block of data
- * this code borrowed from libmpeg2.
- * Note: this uses the 'naive' approach of constant durations,
- * not the real NTSC-like durations that vary dep on repeat first
- * field flags and stuff. */
- buffer = buf->content;
- shift = 0xffffff00;
- for (i=0; i<buf->size; i++) {
- byte = *buffer++;
- if (shift != 0x00000100) {
- shift = (shift | byte) << 8;
- continue;
- }
- /* header code of some kind found */
- /* printf("dxr3: have header %x\n", byte); */
- shift = 0xffffff00;
- if (byte == 0xb3) {
- /* sequence data, also borrowed from libmpeg2 */
- /* will enable have_header_info */
- parse_mpeg_header(this, buffer);
- continue;
- }
- if (byte == 0xb5) {
- /* extension data */
- if ((buffer[0] & 0xf0) == 0x80) {
- /* picture coding extension */
- this->repeat_first_field = (buffer[3] >> 1) & 1;
- }
- /* check if we can keep syncing */
- if (this->repeat_first_field && this->sync_every_frame) {
- /* metronom can't handle variable duration */
- printf("dxr3: non-progressive video detected. "
- "disabling sync_every_frame.\n");
- this->sync_every_frame = 0;
- this->sync_retry = 500; /* see you later */
- }
- if (this->repeat_first_field && this->sync_retry) {
- /* reset counter */
- this->sync_retry = 500;
- }
- continue;
- }
- if (byte != 0x00) {
- /* Don't care what it is. It's not a new frame */
- continue;
- }
- /* we have a code for a new frame */
- if (! this->have_header_info) {
- /* this->width et al may still be undefined */
- continue;
- }
- duration = get_duration(this->frame_rate_code,
- this->repeat_first_field);
- /* pretend like we have decoded a frame */
- img = this->video_out->get_frame (this->video_out,
- this->width,
- this->height,
- this->aspect,
- IMGFMT_MPEG,
- VO_BOTH_FIELDS);
- 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 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->vpts; /* copy so we can free img */
-
- if (this->resync_window == 0 && this->scr && this->enhanced_mode && !scanning_mode) {
- /* we are in sync, so we can lock the stream now */
- printf("dxr3: in sync, stream locked\n");
- dxr3_mvcommand(this->fd_control, MVCOMMAND_SYNC);
- this->resync_window = -RESYNC_WINDOW_SIZE;
- }
- if (this->resync_window != 0 && this->resync_window > -RESYNC_WINDOW_SIZE)
- this->resync_window--;
- }
- else { /* metronom says skip, so don't set vpts */
- printf("dxr3: skip = %d\n", skip);
- vpts = 0;
-
- if (scanning_mode) this->resync_window = 0;
- if (this->resync_window == 0 && this->scr && this->enhanced_mode && !scanning_mode) {
- /* switch off sync mode in the card to allow resyncing */
- printf("dxr3: out of sync, allowing stream resync\n");
- dxr3_mvcommand(this->fd_control, MVCOMMAND_START);
- this->resync_window = RESYNC_WINDOW_SIZE;
- }
- if (this->resync_window != 0 && this->resync_window < RESYNC_WINDOW_SIZE)
- this->resync_window++;
- }
- img->free(img);
- this->last_pts += duration; /* predict vpts */
-
- /* if sync_every_frame was disabled, decrease the counter
- * for a retry
- * (it might be due to crappy studio logos and stuff
- * so we should give the main movie a chance) */
- if (this->sync_retry) {
- this->sync_retry--;
- if (!this->sync_retry) {
- printf("dxr3: retrying sync_every_frame");
- this->sync_every_frame = 1;
- }
- }
- }
-
-
- /* ensure video device is open
- * (we open it late because on occasion the dxr3 video out driver
- * wants to open it) */
- if (this->fd_video < 0) {
- char tmpstr[128];
- 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));
- return;
- }
- }
+ free(this_gen);
+}
- /* We may want to issue a SETPTS, so make sure the scr plugin
- is running and registered. Unfortuantely wa cannot do this
- earlier, because the dxr3's internal scr gets confused
- when started with a closed video device. Maybe this is a
- driver bug and gets fixed somewhen. FIXME: We might then
- want to move this code to dxr3_init. */
- if (!this->scr) {
- int64_t time;
-
- time = this->metronom->get_current_time(
- this->metronom);
-
- this->scr = dxr3scr_init(this);
- this->scr->start(this->scr, time);
- this->metronom->register_scr(
- this->metronom, this->scr);
- if (this->metronom->scr_master == this->scr) {
- printf("dxr3: dxr3scr plugin is master\n");
- } else {
- printf("dxr3: dxr3scr plugin is NOT master\n");
- }
- }
- /* From time to time, update the pts value
- * FIXME: the exact conditions here are a bit uncertain... */
- if (vpts)
- {
- int64_t delay;
-
- delay = vpts - this->metronom->get_current_time(
- this->metronom);
-#if LOG_PTS
- printf("dxr3: SETPTS got %lld expected = %lld (delta %lld) delay = %lld\n",
- vpts, this->last_pts, vpts-this->last_pts, delay);
-#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 */
- 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, &vpts32))
- printf("dxr3: set video pts failed (%s)\n",
- strerror(errno));
- }
- if (delay >= 90000) {
- /* frame more than 1 sec ahead */
- printf("dxr3: WARNING: vpts %lld is %.02f seconds ahead of time!\n",
- vpts, delay/90000.0);
- }
- if (delay < 0) {
- printf("dxr3: WARNING: overdue frame.\n");
- }
- }
-#if LOG_PTS
- else if (buf->pts) {
- printf("dxr3: skip buf->pts = %lld (no vpts) last_vpts = %lld\n",
- buf->pts, this->last_pts);
- }
+static int dxr3_present(xine_t *xine)
+{
+ int info;
+
+ if (xine && xine->video_driver) {
+ info = xine->video_driver->get_property(xine->video_driver, VO_PROP_VO_TYPE);
+#ifdef LOG_VID
+ printf("dxr3_decode_video: dxr3 presence test: info = %d\n", info);
#endif
-
- /* now write the content to the dxr3 mpeg device and, in a dramatic
- break with open source tradition, check the return value */
- written = write(this->fd_video, buf->content, buf->size);
- if (written < 0) {
- if (errno == EAGAIN) {
- printf("dxr3: write to device would block. flushing\n");
- dxr3_flush(this_gen);
- }
- else {
- printf("dxr3: video device write failed (%s)\n",
- strerror(errno));
- }
- return;
- }
- if (written != buf->size)
- printf("dxr3: Could only write %d of %d video bytes.\n",
- written, buf->size);
-
+ if (info != VO_TYPE_DXR3)
+ return 0;
+ }
+ return 1;
}
-static void dxr3_close (video_decoder_t *this_gen)
+static int dxr3_mvcommand(int fd_control, int command)
{
- dxr3_decoder_t *this = (dxr3_decoder_t *) this_gen;
- metronom_t *metronom = this->metronom;
- int64_t cur_offset;
-
- if (this->scr) {
- metronom->unregister_scr(metronom, this->scr);
- this->scr->exit(this->scr);
- this->scr = 0;
- }
-
- /* revert av_offset change done in dxr3_init */
- cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET);
- metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset + 21600);
-
- if (this->fd_video >= 0)
- close(this->fd_video);
- this->fd_video = -1;
-
- this->video_out->close(this->video_out);
- this->have_header_info = 0;
+ em8300_register_t regs;
+
+ regs.microcode_register = 1;
+ regs.reg = 0;
+ regs.val = command;
+
+ return ioctl(fd_control, EM8300_IOCTL_WRITEREG, &regs);
}
-static char *dxr3_get_id(void) {
- return "dxr3-mpeg2";
-}
-
-static void dxr3_update_enhanced_mode(void *this_gen, cfg_entry_t *entry)
+static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer)
{
- ((dxr3_decoder_t*)this_gen)->enhanced_mode = entry->num_value;
- printf("dxr3: mpeg playback: set enhanced mode to %s\n",
- (entry->num_value ? "on" : "off"));
+ this->frame_rate_code = buffer[HEADER_OFFSET+3] & 15;
+ this->height = (buffer[HEADER_OFFSET+0] << 16) |
+ (buffer[HEADER_OFFSET+1] << 8) |
+ buffer[HEADER_OFFSET+2];
+ this->width = ((this->height >> 12) + 15) & ~15;
+ this->height = ((this->height & 0xfff) + 15) & ~15;
+ this->aspect = buffer[HEADER_OFFSET+3] >> 4;
+
+ this->have_header_info = 1;
}
-static void dxr3_update_sync_mode(void *this_gen, cfg_entry_t *entry)
+static int get_duration(int framecode, int repeat_first_field)
{
- ((dxr3_decoder_t*)this_gen)->sync_every_frame = entry->num_value;
- printf("dxr3: set sync_every_frame to %s\n",
- (entry->num_value ? "on" : "off"));
+ int duration;
+
+ switch (framecode) {
+ case 1: /* 23.976 */
+ duration = 3913;
+ break;
+ case 2: /* 24.000 */
+ duration = 3750;
+ break;
+ case 3: /* 25.000 */
+ duration = repeat_first_field ? 5400 : 3600;
+ break;
+ case 4: /* 29.970 */
+ duration = repeat_first_field ? 4505 : 3003;
+ break;
+ case 5: /* 30.000 */
+ duration = 3000;
+ break;
+ case 6: /* 50.000 */
+ duration = 1800;
+ break;
+ case 7: /* 59.940 */
+ duration = 1525;
+ break;
+ case 8: /* 60.000 */
+ duration = 1509;
+ break;
+ default:
+ printf("dxr3_decode_video: warning: unknown frame rate code %d: using PAL\n", framecode);
+ duration = 3600; /* PAL 25fps */
+ break;
+ }
+
+ return duration;
}
-static void dxr3_flush_decoder(void *this_gen, cfg_entry_t *entry)
+static void dxr3_update_priority(void *this_gen, cfg_entry_t *entry)
{
- /* dxr3_decoder_t *this = (dxr3_decoder_t*)this_gen; */
- printf("dxr3: flush requested\n");
-/*
- pthread_kill(this->decoder_thread, SIGINT);
- if (this->fd_video >= 0) {
- close(this->fd_video);
- this->fd_video = -1;
- }
-*/
- dxr3_flush(this_gen);
- /* reset to false, so it'll look like a button in the gui :-) */
- entry->num_value = 0;
+ ((dxr3_decoder_t *)this_gen)->video_decoder.priority = entry->num_value;
+ printf("dxr3_decode_video: setting decoder priority to %d\n",
+ entry->num_value);
}
-static void dxr3_dispose (video_decoder_t *this_gen) {
- free (this_gen);
+static void dxr3_update_sync_mode(void *this_gen, cfg_entry_t *entry)
+{
+ ((dxr3_decoder_t *)this_gen)->sync_every_frame = entry->num_value;
+ printf("dxr3_decode_video: setting sync_every_frame to %s\n",
+ (entry->num_value ? "on" : "off"));
}
-video_decoder_t *init_video_decoder_plugin (int iface_version,
- xine_t *xine)
+static void dxr3_update_enhanced_mode(void *this_gen, cfg_entry_t *entry)
{
- dxr3_decoder_t *this ;
- config_values_t *cfg;
- char *tmpstr;
- int dashpos;
- int result;
-
- if (iface_version != 8) {
- printf( "dxr3_decode_video: plugin doesn't support plugin API version %d.\n"
- "dxr3_decode_video: this means there's a version mismatch between xine and this\n"
- "dxr3_decode_video: decoder plugin. Installing current plugins should help.\n",
- iface_version);
- return NULL;
- }
-
- cfg = xine->config;
- 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';
- }
-
- result = dxr3_presence_test ( xine );
- if (!result) return NULL;
-
- this = (dxr3_decoder_t *) malloc (sizeof (dxr3_decoder_t));
-
- this->video_decoder.interface_version = iface_version;
- this->video_decoder.can_handle = dxr3_can_handle;
- this->video_decoder.init = dxr3_init;
- this->video_decoder.decode_data = dxr3_decode_data;
- this->video_decoder.close = dxr3_close;
- this->video_decoder.get_identifier = dxr3_get_id;
- this->video_decoder.flush = dxr3_flush;
- this->video_decoder.reset = dxr3_reset;
- this->video_decoder.dispose = dxr3_dispose;
- this->video_decoder.priority = cfg->register_num(cfg,
- "dxr3.decoder_priority", 10, "Dxr3: video decoder priority", NULL, NULL, NULL);
-
- this->config = cfg;
- this->metronom = xine->metronom;
- this->frame_rate_code = 0;
- this->repeat_first_field = 0;
- this->sync_every_frame = 1;
-
- 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,
- "dxr3.sync_every_frame",
- 0,
- "Try to sync video every frame",
- "This is relevant for progressive video only (most PAL films)",
- dxr3_update_sync_mode, this);
-
- this->sync_retry = 0;
-
- this->enhanced_mode = cfg->register_bool(cfg,
- "dxr3.alt_play_mode",
- 1,
- "Use alternate Play mode",
- "Enabling this option will utilise a slightly different play mode",
- dxr3_update_enhanced_mode, this);
-
- /* a boolean that's really a button; request a decoder flush */
- cfg->register_bool(cfg, "dxr3.flush", 0, "Flush decoder now",
- "Flushing the decoder might unfreeze playback or restore sync",
- dxr3_flush_decoder, this);
-
- if(this->enhanced_mode)
- printf("dxr3: Using Mode 6 for playback\n");
- this->have_header_info = 0;
- this->in_buffer_fill = 0;
- return (video_decoder_t *) this;
+ ((dxr3_decoder_t *)this_gen)->enhanced_mode = entry->num_value;
+ printf("dxr3_decode_video: setting enhanced mode to %s\n",
+ (entry->num_value ? "on" : "off"));
}
-
diff --git a/src/dxr3/dxr3_scr.c b/src/dxr3/dxr3_scr.c
new file mode 100644
index 000000000..2ddfb6844
--- /dev/null
+++ b/src/dxr3/dxr3_scr.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: dxr3_scr.c,v 1.1 2002/05/06 11:26:37 jcdutton Exp $
+ */
+
+/* dxr3 scr plugin.
+ * enables xine to use the internal clock of the card as its
+ * global time reference.
+ */
+
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "xine_internal.h"
+#include "xineutils.h"
+#include "dxr3.h"
+
+#include "dxr3_scr.h"
+
+#define LOG_SCR 0
+
+
+/* functions required by xine api */
+static int dxr3_scr_get_priority(scr_plugin_t *scr);
+static void dxr3_scr_start(scr_plugin_t *scr, int64_t vpts);
+static int64_t dxr3_scr_get_current(scr_plugin_t *scr);
+static void dxr3_scr_adjust(scr_plugin_t *scr, int64_t vpts);
+static int dxr3_scr_set_speed(scr_plugin_t *scr, int speed);
+static void dxr3_scr_exit(scr_plugin_t *scr);
+
+/* helper function */
+static int dxr3_mvcommand(int fd_control, int command);
+static void dxr3_scr_update_priority(void *this_gen, cfg_entry_t *entry);
+
+
+dxr3_scr_t *dxr3_scr_init(xine_t *xine)
+{
+ dxr3_scr_t *this;
+ char *confstr;
+
+ this = (dxr3_scr_t *)malloc(sizeof(dxr3_scr_t));
+
+ confstr = xine->config->register_string(xine->config,
+ CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, NULL, NULL);
+ if ((this->fd_control = open(confstr, O_WRONLY)) < 0) {
+ printf("dxr3_scr: Failed to open control device %s (%s)\n",
+ confstr, strerror(errno));
+ free(this);
+ return NULL;
+ }
+
+ this->scr_plugin.interface_version = 2;
+ this->scr_plugin.get_priority = dxr3_scr_get_priority;
+ this->scr_plugin.start = dxr3_scr_start;
+ this->scr_plugin.get_current = dxr3_scr_get_current;
+ this->scr_plugin.adjust = dxr3_scr_adjust;
+ this->scr_plugin.set_speed = dxr3_scr_set_speed;
+ this->scr_plugin.exit = dxr3_scr_exit;
+
+ this->priority = xine->config->register_num(
+ xine->config, "dxr3.scr_priority", 10, "Dxr3: SCR plugin priority",
+ "Scr priorities greater 5 make the dxr3 xine's master clock.",
+ dxr3_scr_update_priority, this);
+ this->offset = 0;
+ this->last_pts = 0;
+ this->scanning = 0;
+
+ pthread_mutex_init(&this->mutex, NULL);
+
+#if LOG_SCR
+ printf("dxr3_scr: init complete\n");
+#endif
+ return this;
+}
+
+
+static int dxr3_scr_get_priority(scr_plugin_t *scr)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+ return this->priority;
+}
+
+static void dxr3_scr_start(scr_plugin_t *scr, int64_t vpts)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+ uint32_t vpts32 = vpts >> 1;
+
+ pthread_mutex_lock(&this->mutex);
+ this->last_pts = vpts32;
+ this->offset = vpts - ((int64_t)vpts32 << 1);
+ if (ioctl(this->fd_control, EM8300_IOCTL_SCR_SET, &vpts32))
+ printf("dxr3_scr: start failed (%s)\n", strerror(errno));
+#if LOG_SCR
+ printf("dxr3_scr: started with vpts %lld\n", vpts);
+#endif
+ /* mis-use vpts32 to set the clock speed to 0x900, which is normal speed */
+ vpts32 = 0x900;
+ ioctl(this->fd_control, EM8300_IOCTL_SCR_SETSPEED, &vpts32);
+ this->scanning = 0;
+ pthread_mutex_unlock(&this->mutex);
+}
+
+static int64_t dxr3_scr_get_current(scr_plugin_t *scr)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+ uint32_t pts;
+ int64_t current;
+
+ pthread_mutex_lock(&this->mutex);
+ if (ioctl(this->fd_control, EM8300_IOCTL_SCR_GET, &pts))
+ printf("dxr3_scr: get current failed (%s)\n", strerror(errno));
+ if (this->last_pts > 0xF0000000 && pts < 0x10000000)
+ /* wrap around detected, compensate with offset */
+ this->offset += (int64_t)1 << 33;
+ this->last_pts = pts;
+ current = ((int64_t)pts << 1) + this->offset;
+ pthread_mutex_unlock(&this->mutex);
+
+ return current;
+}
+
+static void dxr3_scr_adjust(scr_plugin_t *scr, int64_t vpts)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+ uint32_t current_pts32;
+ int32_t offset32;
+
+ pthread_mutex_lock(&this->mutex);
+ if (ioctl(this->fd_control, EM8300_IOCTL_SCR_GET, &current_pts32))
+ printf("dxr3_scr: adjust get failed (%s)\n", strerror(errno));
+ this->last_pts = current_pts32;
+ this->offset = vpts - ((int64_t)current_pts32 << 1);
+ offset32 = this->offset / 4;
+ /* kernel driver ignores diffs < 7200, so abs(offset32) must be > 7200 / 4 */
+ if (offset32 < -7200/4 || offset32 > 7200/4) {
+ uint32_t vpts32 = vpts >> 1;
+ if (ioctl(this->fd_control, EM8300_IOCTL_SCR_SET, &vpts32))
+ printf("dxr3_scr: adjust set failed (%s)\n", strerror(errno));
+ this->last_pts = vpts32;
+ this->offset = vpts - ((int64_t)vpts32 << 1);
+ }
+#if LOG_SCR
+ printf("dxr3_scr: adjusted to vpts %lld\n", vpts);
+#endif
+ pthread_mutex_unlock(&this->mutex);
+}
+
+static int dxr3_scr_set_speed(scr_plugin_t *scr, int speed)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+ uint32_t em_speed;
+ int playmode;
+
+ switch (speed) {
+ case SPEED_PAUSE:
+ em_speed = 0;
+ playmode = MVCOMMAND_PAUSE;
+ break;
+ case SPEED_SLOW_4:
+ em_speed = 0x900 / 4;
+ playmode = MVCOMMAND_START;
+ break;
+ case SPEED_SLOW_2:
+ em_speed = 0x900 / 2;
+ playmode = MVCOMMAND_START;
+ break;
+ case SPEED_NORMAL:
+ em_speed = 0x900;
+ playmode = MVCOMMAND_SYNC;
+ break;
+ case SPEED_FAST_2:
+ em_speed = 0x900 * 2;
+ playmode = MVCOMMAND_START;
+ break;
+ case SPEED_FAST_4:
+ em_speed = 0x900 * 4;
+ playmode = MVCOMMAND_START;
+ break;
+ default:
+ speed = em_speed = 0;
+ playmode = MVCOMMAND_PAUSE;
+ }
+
+ if (dxr3_mvcommand(this->fd_control, playmode))
+ printf("dxr3_scr: failed to playmode (%s)\n", strerror(errno));
+
+ if(em_speed > 0x900)
+ this->scanning = 1;
+ else
+ this->scanning = 0;
+
+ if (ioctl(this->fd_control, EM8300_IOCTL_SCR_SETSPEED, &em_speed))
+ printf("dxr3_scr: failed to set speed (%s)\n", strerror(errno));
+
+#if LOG_SCR
+ printf("dxr3_scr: speed set to mode %d\n", speed);
+#endif
+ return speed;
+}
+
+static void dxr3_scr_exit(scr_plugin_t *scr)
+{
+ dxr3_scr_t *this = (dxr3_scr_t *)scr;
+
+ pthread_mutex_destroy(&this->mutex);
+ free(this);
+}
+
+
+static int dxr3_mvcommand(int fd_control, int command)
+{
+ em8300_register_t regs;
+
+ regs.microcode_register = 1;
+ regs.reg = 0;
+ regs.val = command;
+
+ return ioctl(fd_control, EM8300_IOCTL_WRITEREG, &regs);
+}
+
+static void dxr3_scr_update_priority(void *this_gen, cfg_entry_t *entry)
+{
+ ((dxr3_scr_t *)this_gen)->priority = entry->num_value;
+ printf("dxr3_scr: setting scr priority to %d\n",
+ entry->num_value);
+}
diff --git a/src/dxr3/dxr3_scr.h b/src/dxr3/dxr3_scr.h
new file mode 100644
index 000000000..b0814ebd8
--- /dev/null
+++ b/src/dxr3/dxr3_scr.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2000-2002 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: dxr3_scr.h,v 1.1 2002/05/06 11:26:37 jcdutton Exp $
+ */
+
+/* plugin structure */
+typedef struct dxr3_scr_s {
+ scr_plugin_t scr_plugin;
+ pthread_mutex_t mutex;
+
+ int fd_control; /* to access the dxr3 control device */
+
+ int priority;
+ 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 */
+ int scanning; /* are we in a scanning mode */
+} dxr3_scr_t;
+
+/* plugin initialization function */
+dxr3_scr_t *dxr3_scr_init(xine_t *xine);
diff --git a/src/dxr3/dxr3_video_out.c b/src/dxr3/dxr3_video_out.c
index 727cd5cae..29edf5c5e 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.15 2002/04/04 00:08:36 miguelfreitas Exp $
+ * $Id: dxr3_video_out.c,v 1.16 2002/05/06 11:26:37 jcdutton Exp $
*
* mpeg1 encoding video out plugin for the dxr3.
*
@@ -162,13 +162,13 @@ int dxr3_fame_init(dxr3_driver_t *);
static uint32_t dxr3_get_capabilities (vo_driver_t *this_gen)
{
- return VO_CAP_YV12 | VO_CAP_YUY2 |
- VO_CAP_SATURATION | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST;
+ return VO_CAP_YV12 | VO_CAP_YUY2 |
+ VO_CAP_SATURATION | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST;
}
static void dummy_frame_field (vo_frame_t *vo_img, int which_field)
{
- /* dummy function */
+ /* dummy function */
}
static void dxr3_frame_dispose (vo_frame_t *frame_gen)
@@ -201,9 +201,9 @@ static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen)
}
static void dxr3_update_frame_format (vo_driver_t *this_gen,
- vo_frame_t *frame_gen,
- uint32_t width, uint32_t height,
- int ratio_code, int format, int flags)
+ vo_frame_t *frame_gen,
+ uint32_t width, uint32_t height,
+ int ratio_code, int format, int flags)
{
dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
int aspect,i;
@@ -213,7 +213,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
/* update the overlay window co-ords if required */
dxr3_overlay_update(this);
- /* reset the copy calls counter (number of calls to dxr3_frame_copy) */
+ /* reset the copy calls counter (number of calls to dxr3_frame_copy) */
frame->copy_calls = 0;
frame->vo_frame.driver = this_gen;
@@ -221,49 +221,49 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
oheight = this->oheight;
if (format == IMGFMT_MPEG) { /* talking to dxr3 decoder */
- int aspect;
- /* a bit of a hack. we must release the em8300_mv fd for
- * the dxr3 decoder plugin */
- if (this->fd_video >= 0) {
- close(this->fd_video);
- this->fd_video = CLOSED_FOR_DECODER;
- }
- /* for mpeg source, we don't have to do much. */
- this->video_width = width;
- this->video_height = height;
- this->video_aspect = ratio_code;
- /* remember, there are no buffers malloc'ed for this frame!
- * the dxr3 decoder plugin is cool about this */
- frame->width = width;
- frame->height = height;
- frame->oheight = oheight;
- if (frame->mem) {
- free (frame->mem);
- frame->mem = NULL;
- frame->real_base[0] = frame->real_base[1]
- = frame->real_base[2] = NULL;
- frame_gen->base[0] = frame_gen->base[1]
- = frame_gen->base[2] = NULL;
- }
- if (ratio_code < 3 || ratio_code>4)
- aspect = ASPECT_FULL;
- else
- aspect = ASPECT_ANAMORPHIC;
- if(this->aspectratio!=aspect)
- dxr3_set_property ((vo_driver_t*)this, VO_PROP_ASPECT_RATIO, aspect);
- return;
+ int aspect;
+ /* a bit of a hack. we must release the em8300_mv fd for
+ * the dxr3 decoder plugin */
+ if (this->fd_video >= 0) {
+ close(this->fd_video);
+ this->fd_video = CLOSED_FOR_DECODER;
+ }
+ /* for mpeg source, we don't have to do much. */
+ this->video_width = width;
+ this->video_height = height;
+ this->video_aspect = ratio_code;
+ /* remember, there are no buffers malloc'ed for this frame!
+ * the dxr3 decoder plugin is cool about this */
+ frame->width = width;
+ frame->height = height;
+ frame->oheight = oheight;
+ if (frame->mem) {
+ free (frame->mem);
+ frame->mem = NULL;
+ frame->real_base[0] = frame->real_base[1]
+ = frame->real_base[2] = NULL;
+ frame_gen->base[0] = frame_gen->base[1]
+ = frame_gen->base[2] = NULL;
+ }
+ if (ratio_code < 3 || ratio_code>4)
+ aspect = ASPECT_FULL;
+ else
+ aspect = ASPECT_ANAMORPHIC;
+ if(this->aspectratio!=aspect)
+ dxr3_set_property ((vo_driver_t*)this, VO_PROP_ASPECT_RATIO, aspect);
+ return;
}
/* the following is for the mpeg encoding part only */
if (this->fd_video == CLOSED_FOR_DECODER) { /* decoder should have released it */
- this->fd_video = CLOSED_FOR_ENCODER; /* allow encoder to reopen it */
- this->need_redraw = 1;
+ this->fd_video = CLOSED_FOR_ENCODER; /* allow encoder to reopen it */
+ this->need_redraw = 1;
}
if (this->add_bars == 0) {
- /* don't add black bars; assume source is in 4:3 */
- ratio_code = XINE_ASPECT_RATIO_4_3;
+ /* don't add black bars; assume source is in 4:3 */
+ ratio_code = XINE_ASPECT_RATIO_4_3;
}
/* check aspect ratio, see if we need to add black borders */
@@ -308,16 +308,16 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
if (! this->enc) {
/* no encoder plugin! Let's bug the user! */
printf(
- "dxr3: ********************************************************\n"
- "dxr3: * *\n"
- "dxr3: * need an mpeg encoder to play non-mpeg videos on dxr3 *\n"
- "dxr3: * read the README.dxr3 for details. *\n"
- "dxr3: * (if you get this message while trying to play an *\n"
- "dxr3: * mpeg video, there is something wrong with the dxr3 *\n"
- "dxr3: * decoder plugin. check if it is set up correctly) *\n"
- "dxr3: * *\n"
- "dxr3: ********************************************************\n"
- );
+ "dxr3: ********************************************************\n"
+ "dxr3: * *\n"
+ "dxr3: * need an mpeg encoder to play non-mpeg videos on dxr3 *\n"
+ "dxr3: * read the README.dxr3 for details. *\n"
+ "dxr3: * (if you get this message while trying to play an *\n"
+ "dxr3: * mpeg video, there is something wrong with the dxr3 *\n"
+ "dxr3: * decoder plugin. check if it is set up correctly) *\n"
+ "dxr3: * *\n"
+ "dxr3: ********************************************************\n"
+ );
}
if (this->enc && this->enc->on_update_format)
@@ -327,7 +327,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
/* if dimensions changed, we need to re-allocate frame memory */
if ((frame->width != width) || (frame->height != height) ||
- (frame->oheight != oheight)) {
+ (frame->oheight != oheight)) {
if (frame->mem) {
free (frame->mem);
frame->mem = NULL;
@@ -340,7 +340,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
/* planar format, only base[0] */
/* add one extra line for field swap stuff */
frame->real_base[0] = malloc_aligned(16, (image_size+width)*2,
- (void**)&frame->mem);
+ (void**)&frame->mem);
/* don't use first line */
frame->real_base[0] += width * 2;
frame->real_base[1] = frame->real_base[2] = 0;
@@ -352,7 +352,7 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
/* fill with black (yuy2 16,128,16,128,...) */
memset(frame->real_base[0], 128, 2*image_size); /* U and V */
for (i=0; i<2*image_size; i+=2)
- *(frame->real_base[0]+i) = 16; /* Y */
+ *(frame->real_base[0]+i) = 16; /* Y */
}
else { /* IMGFMT_YV12 */
image_size = width * oheight; /* includes black bars */
@@ -377,18 +377,18 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
}
if (this->swap_fields != frame->swap_fields) {
- if (format == IMGFMT_YUY2) {
- if (this->swap_fields)
- frame->vo_frame.base[0] -= width *2;
- else
- frame->vo_frame.base[0] += width *2;
- }
- else {
- if (this->swap_fields)
- frame->vo_frame.base[0] -= width;
- else
- frame->vo_frame.base[0] += width;
- }
+ if (format == IMGFMT_YUY2) {
+ if (this->swap_fields)
+ frame->vo_frame.base[0] -= width *2;
+ else
+ frame->vo_frame.base[0] += width *2;
+ }
+ else {
+ if (this->swap_fields)
+ frame->vo_frame.base[0] -= width;
+ else
+ frame->vo_frame.base[0] += width;
+ }
}
frame->width = width;
@@ -402,24 +402,24 @@ static void dxr3_update_frame_format (vo_driver_t *this_gen,
int dxr3_redraw_needed(vo_driver_t *this_gen)
{
- dxr3_driver_t *this = (dxr3_driver_t *)this_gen;
-
- dxr3_overlay_update(this);
+ dxr3_driver_t *this = (dxr3_driver_t *)this_gen;
+
+ dxr3_overlay_update(this);
- if (this->need_redraw) {
- this->need_redraw = 0;
- return 1;
- }
+ if (this->need_redraw) {
+ this->need_redraw = 0;
+ return 1;
+ }
- return 0;
+ return 0;
}
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 = (dxr3_driver_t *) frame_gen->driver;
- if (frame_gen->format != IMGFMT_MPEG && this->enc && this->enc->on_frame_copy)
- this->enc->on_frame_copy(this, frame, src);
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ dxr3_driver_t *this = (dxr3_driver_t *) frame_gen->driver;
+ if (frame_gen->format != IMGFMT_MPEG && this->enc && this->enc->on_frame_copy)
+ this->enc->on_frame_copy(this, frame, src);
}
static void dxr3_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
@@ -439,197 +439,197 @@ static void dxr3_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
static void dxr3_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
vo_overlay_t *overlay)
{
- /* FIXME: We only blend non-mpeg frames here.
- Is there any way to provide overlays for mpeg content? Subpictures? */
- if ( frame_gen->format != IMGFMT_MPEG )
- {
- dxr3_frame_t *frame = (dxr3_frame_t*)frame_gen;
-
- if (overlay->rle) {
- if( frame_gen->format == IMGFMT_YV12 )
- blend_yuv( frame->vo_frame.base, overlay, frame->width, frame->height);
- else
- blend_yuy2( frame->vo_frame.base[0], overlay, frame->width, frame->height);
- }
- }
+ /* FIXME: We only blend non-mpeg frames here.
+ Is there any way to provide overlays for mpeg content? Subpictures? */
+ if ( frame_gen->format != IMGFMT_MPEG )
+ {
+ dxr3_frame_t *frame = (dxr3_frame_t*)frame_gen;
+
+ if (overlay->rle) {
+ if( frame_gen->format == IMGFMT_YV12 )
+ blend_yuv( frame->vo_frame.base, overlay, frame->width, frame->height);
+ else
+ blend_yuy2( frame->vo_frame.base[0], overlay, frame->width, frame->height);
+ }
+ }
}
void dxr3_exit (vo_driver_t *this_gen)
{
- dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
- if (this->enc && this->enc->on_close)
- this->enc->on_close(this);
- printf("dxr3: vo exit called\n");
+ if (this->enc && this->enc->on_close)
+ this->enc->on_close(this);
+ printf("dxr3: vo exit called\n");
- if(this->overlay_enabled)
- dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF);
+ if(this->overlay_enabled)
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF);
}
void dxr3_update_add_bars(void *data, cfg_entry_t* entry)
{
- dxr3_driver_t* this = (dxr3_driver_t*)data;
- this->add_bars = entry->num_value;
- printf("dxr3: add bars to correct a.r. is %s\n",
- (this->add_bars ? "on" : "off"));
+ dxr3_driver_t* this = (dxr3_driver_t*)data;
+ this->add_bars = entry->num_value;
+ printf("dxr3: add bars to correct a.r. is %s\n",
+ (this->add_bars ? "on" : "off"));
}
void dxr3_update_swap_fields(void *data, cfg_entry_t* entry)
{
- dxr3_driver_t* this = (dxr3_driver_t*)data;
- this->swap_fields = entry->num_value;
- printf("dxr3: set swap field to %s\n",
- (this->swap_fields ? "on" : "off"));
+ dxr3_driver_t* this = (dxr3_driver_t*)data;
+ this->swap_fields = entry->num_value;
+ printf("dxr3: set swap field to %s\n",
+ (this->swap_fields ? "on" : "off"));
}
static void dxr3_update_enhanced_mode(void *this_gen, cfg_entry_t *entry)
{
- ((dxr3_driver_t*)this_gen)->enhanced_mode = entry->num_value;
- printf("dxr3: encode: set enhanced mode to %s\n",
- (entry->num_value ? "on" : "off"));
+ ((dxr3_driver_t*)this_gen)->enhanced_mode = entry->num_value;
+ printf("dxr3: encode: set enhanced mode to %s\n",
+ (entry->num_value ? "on" : "off"));
}
vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
{
- dxr3_driver_t *this;
- char tmpstr[100];
- const char *encoder;
- char *available_encoders,*default_encoder;
- char *confstr;
- int dashpos;
-
- /*
- * allocate plugin struct
- */
+ dxr3_driver_t *this;
+ char tmpstr[100];
+ const char *encoder;
+ char *available_encoders,*default_encoder;
+ char *confstr;
+ int dashpos;
+
+ /*
+ * allocate plugin struct
+ */
printf("dxr3_video_out:init_plugin\n");
- this = malloc (sizeof (dxr3_driver_t));
-
- if (!this) {
- printf ("video_out_dxr3: malloc failed\n");
- return NULL;
- }
-
- memset (this, 0, sizeof(dxr3_driver_t));
-
- this->vo_driver.get_capabilities = dxr3_get_capabilities;
- this->vo_driver.alloc_frame = dxr3_alloc_frame;
- this->vo_driver.update_frame_format = dxr3_update_frame_format;
- this->vo_driver.display_frame = dxr3_display_frame;
- this->vo_driver.overlay_blend = dxr3_overlay_blend;
- this->vo_driver.get_property = dxr3_get_property;
- this->vo_driver.set_property = dxr3_set_property;
- this->vo_driver.get_property_min_max = dxr3_get_property_min_max;
- this->vo_driver.gui_data_exchange = dxr3_gui_data_exchange;
- this->vo_driver.redraw_needed = dxr3_redraw_needed;
- this->vo_driver.exit = dxr3_exit;
- this->config=config;
-
- this->swap_fields = config->register_bool(config, "dxr3.enc_swap_fields", 0, "swap odd and even lines", NULL, dxr3_update_swap_fields, this);
-
- this->add_bars = config->register_bool(config, "dxr3.enc_add_bars", 1, "Add black bars to correct aspect ratio", "If disabled, will assume source has 4:3 a.r.", dxr3_update_add_bars, this);
-
- 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 */
- 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';
- }
-
- 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",
- tmpstr, strerror(errno));
- return 0;
- }
+ this = malloc (sizeof (dxr3_driver_t));
+
+ if (!this) {
+ printf ("video_out_dxr3: malloc failed\n");
+ return NULL;
+ }
+
+ memset (this, 0, sizeof(dxr3_driver_t));
+
+ this->vo_driver.get_capabilities = dxr3_get_capabilities;
+ this->vo_driver.alloc_frame = dxr3_alloc_frame;
+ this->vo_driver.update_frame_format = dxr3_update_frame_format;
+ this->vo_driver.display_frame = dxr3_display_frame;
+ this->vo_driver.overlay_blend = dxr3_overlay_blend;
+ this->vo_driver.get_property = dxr3_get_property;
+ this->vo_driver.set_property = dxr3_set_property;
+ this->vo_driver.get_property_min_max = dxr3_get_property_min_max;
+ this->vo_driver.gui_data_exchange = dxr3_gui_data_exchange;
+ this->vo_driver.redraw_needed = dxr3_redraw_needed;
+ this->vo_driver.exit = dxr3_exit;
+ this->config=config;
+
+ this->swap_fields = config->register_bool(config, "dxr3.enc_swap_fields", 0, "swap odd and even lines", NULL, dxr3_update_swap_fields, this);
+
+ this->add_bars = config->register_bool(config, "dxr3.enc_add_bars", 1, "Add black bars to correct aspect ratio", "If disabled, will assume source has 4:3 a.r.", dxr3_update_add_bars, this);
+
+ 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 */
+ 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';
+ }
+
+ 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",
+ tmpstr, strerror(errno));
+ return 0;
+ }
/* output mpeg to file instead of dxr3? */
this->file_out = config->register_string(config, "dxr3.outputfile", "<none>", "dxr3: output file of encoded mpeg video for debugging",NULL,NULL,NULL);
if (this->file_out && strcmp(this->file_out, "<none>")) {
- this->fd_video = open(this->file_out, O_WRONLY | O_CREAT);
- if (this->fd_video < 0) {
- perror("dxr3: failed to open output file");
- return 0;
- }
- }
- else {
- /* open video device */
- 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));
- return 0;
- }
- /* close now and and let the encoders reopen if they want */
- close(this->fd_video);
- this->fd_video = CLOSED_FOR_DECODER;
- }
-
- /* which encoder to use? Whadda we got? */
- default_encoder = 0;
- /* memory leak... but config doesn't copy our help string :-( */
- available_encoders = malloc(256);
- strcpy(available_encoders, "Mpeg1 encoder. Options: ");
+ this->fd_video = open(this->file_out, O_WRONLY | O_CREAT);
+ if (this->fd_video < 0) {
+ perror("dxr3: failed to open output file");
+ return 0;
+ }
+ }
+ else {
+ /* open video device */
+ 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));
+ return 0;
+ }
+ /* close now and and let the encoders reopen if they want */
+ close(this->fd_video);
+ this->fd_video = CLOSED_FOR_DECODER;
+ }
+
+ /* which encoder to use? Whadda we got? */
+ default_encoder = 0;
+ /* memory leak... but config doesn't copy our help string :-( */
+ available_encoders = malloc(256);
+ strcpy(available_encoders, "Mpeg1 encoder. Options: ");
#ifdef HAVE_LIBFAME
- default_encoder = "fame";
- strcat(available_encoders, "\"fame\" (very fast, good quality) ");
+ default_encoder = "fame";
+ strcat(available_encoders, "\"fame\" (very fast, good quality) ");
#endif
#ifdef HAVE_LIBRTE
- default_encoder = "rte";
- strcat(available_encoders, "\"rte\" (fast, high quality) ");
+ default_encoder = "rte";
+ strcat(available_encoders, "\"rte\" (fast, high quality) ");
#endif
- printf("dxr3: %s\n", available_encoders);
- this->enc = 0;
- if (default_encoder) {
- encoder = config->register_string(config, "dxr3.encoder",
- default_encoder, available_encoders, NULL, NULL, NULL);
+ printf("dxr3: %s\n", available_encoders);
+ this->enc = 0;
+ if (default_encoder) {
+ encoder = config->register_string(config, "dxr3.encoder",
+ default_encoder, available_encoders, NULL, NULL, NULL);
#ifdef HAVE_LIBRTE
- if (! strcmp(encoder, "rte"))
- if ( dxr3_rte_init(this) )
- return 0;
+ if (! strcmp(encoder, "rte"))
+ if ( dxr3_rte_init(this) )
+ return 0;
#endif
#ifdef HAVE_LIBFAME
- if (! strcmp(encoder, "fame"))
- if ( dxr3_fame_init(this) )
- return 0;
+ if (! strcmp(encoder, "fame"))
+ if ( dxr3_fame_init(this) )
+ return 0;
#endif
- if (this->enc == 0) {
- printf(
+ if (this->enc == 0) {
+ printf(
"dxr3: mpeg encoder \"%s\" not compiled in or not supported.\n"
"dxr3: valid options are %s\n", encoder, available_encoders);
- }
- }
- else {
- printf(
+ }
+ }
+ else {
+ printf(
"dxr3: no mpeg encoder compiled in.\n"
"dxr3: that's ok, you don't need if for mpeg video like DVDs, but\n"
"dxr3: you will not be able to play non-mpeg content using this video out\n"
"dxr3: driver. See the README.dxr3 for details on configuring an encoder.\n"
- );
- }
-
- /* default values */
- this->overlay_enabled = 0;
- this->aspectratio = ASPECT_FULL;
-
- dxr3_read_config(this, visual_gen);
-
- if (this->overlay_enabled) {
- dxr3_get_keycolor(this);
- dxr3_overlay_buggy_preinit(&this->overlay, this->fd_control);
- }
-
- return &this->vo_driver;
+ );
+ }
+
+ /* default values */
+ this->overlay_enabled = 0;
+ this->aspectratio = ASPECT_FULL;
+
+ dxr3_read_config(this, visual_gen);
+
+ if (this->overlay_enabled) {
+ dxr3_get_keycolor(this);
+ dxr3_overlay_buggy_preinit(&this->overlay, this->fd_control);
+ }
+
+ return &this->vo_driver;
}
static vo_info_t vo_info_dxr3 = {
@@ -642,7 +642,7 @@ static vo_info_t vo_info_dxr3 = {
vo_info_t *get_video_out_plugin_info()
{
- return &vo_info_dxr3;
+ return &vo_info_dxr3;
}
diff --git a/src/dxr3/dxr3_video_out.h b/src/dxr3/dxr3_video_out.h
index 847b41f50..31e28971b 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.19 2002/04/04 00:08:36 miguelfreitas Exp $
+ * $Id: dxr3_video_out.h,v 1.20 2002/05/06 11:26:37 jcdutton Exp $
*
*/
@@ -63,105 +63,105 @@
#define CLOSED_FOR_ENCODER -2
struct coeff {
- float k,m;
+ float k,m;
};
typedef struct {
- int fd_control;
-
- int xoffset;
- int yoffset;
- int xcorr;
- int jitter;
- int stability;
- int colorkey;
- float color_interval;
- int screen_xres;
- int screen_yres;
- int screen_depth;
-
- struct coeff colcal_upper[3];
- struct coeff colcal_lower[3];
+ int fd_control;
+
+ int xoffset;
+ int yoffset;
+ int xcorr;
+ int jitter;
+ int stability;
+ int colorkey;
+ float color_interval;
+ int screen_xres;
+ int screen_yres;
+ int screen_depth;
+
+ struct coeff colcal_upper[3];
+ struct coeff colcal_lower[3];
} dxr3_overlay_t;
typedef enum { ENC_FAME, ENC_RTE } encoder_type;
typedef struct encoder_data_s encoder_data_t;
typedef struct dxr3_driver_s {
- vo_driver_t vo_driver;
- config_values_t *config;
- int fd_control;
- int fd_video;
- int aspectratio;
- int tv_mode;
- int enhanced_mode; /* enhanced play mode */
- int need_redraw;
- em8300_bcs_t bcs;
- char devname[128];
- char devnum[3];
-
- /* for encoder plugin */
- encoder_data_t *enc; /* encoder data */
- double fps; /* frames per second */
- int format; /* color format */
- const char *file_out;
- int swap_fields; /* swap fields */
- int add_bars; /* add black bars to correct a.r. */
- /* height after adding black bars to correct a.r. */
- int oheight;
- int top_bar; /* number of lines in top black bar */
- /* input height (before adding black bars) */
- int video_iheight;
- /* output height (after adding bars) */
- int video_height;
-
- /* for overlay */
- dxr3_overlay_t overlay;
- Display *display;
- Drawable win;
- GC gc;
- XColor color;
- int xpos, ypos;
- int width, height;
- int overlay_enabled;
- int tv_switchable; /* can switch from overlay<->tvout */
- int fullscreen_rectangle;
- float desired_ratio;
-
- int zoom_enabled; /* zoomed 16:9 mode */
-
- int video_width;
- int video_aspect;
-
- char *user_data;
-
- void (*frame_output_cb) (void *user_data,
- int video_width, int video_height,
- int *dest_x, int *dest_y,
+ vo_driver_t vo_driver;
+ config_values_t *config;
+ int fd_control;
+ int fd_video;
+ int aspectratio;
+ int tv_mode;
+ int enhanced_mode; /* enhanced play mode */
+ int need_redraw;
+ em8300_bcs_t bcs;
+ char devname[128];
+ char devnum[3];
+
+ /* for encoder plugin */
+ encoder_data_t *enc; /* encoder data */
+ double fps; /* frames per second */
+ int format; /* color format */
+ const char *file_out;
+ int swap_fields; /* swap fields */
+ int add_bars; /* add black bars to correct a.r. */
+ /* height after adding black bars to correct a.r. */
+ int oheight;
+ int top_bar; /* number of lines in top black bar */
+ /* input height (before adding black bars) */
+ int video_iheight;
+ /* output height (after adding bars) */
+ int video_height;
+
+ /* for overlay */
+ dxr3_overlay_t overlay;
+ Display *display;
+ Drawable win;
+ GC gc;
+ XColor color;
+ int xpos, ypos;
+ int width, height;
+ int overlay_enabled;
+ int tv_switchable; /* can switch from overlay<->tvout */
+ int fullscreen_rectangle;
+ float desired_ratio;
+
+ int zoom_enabled; /* zoomed 16:9 mode */
+
+ int video_width;
+ int video_aspect;
+
+ char *user_data;
+
+ void (*frame_output_cb) (void *user_data,
+ int video_width, int video_height,
+ int *dest_x, int *dest_y,
int *dest_height, int *dest_width,
int *win_x, int *win_u);
-/* void (*frame_output_cb) (char *userdata, int video_width,
- int video_height, int *dest_x,
- int *dest_y, int *dest_height, int *dest_width);
+/* void (*frame_output_cb) (char *userdata, int video_width,
+ int video_height, int *dest_x,
+ int *dest_y, int *dest_height, int *dest_width);
*/
} dxr3_driver_t;
typedef struct dxr3_frame_s {
vo_frame_t vo_frame;
int width, height,oheight;
- uint8_t *mem; /* allocated for YV12 or YUY2 buffers */
- uint8_t *real_base[3]; /* yuv/yuy2 buffers in mem aligned on 16 */
- int copy_calls; /* counts calls to dxr3_frame_copy function */
- int swap_fields; /* shifts Y buffer one line to exchange odd/even lines*/
+ uint8_t *mem; /* allocated for YV12 or YUY2 buffers */
+ uint8_t *real_base[3]; /* yuv/yuy2 buffers in mem aligned on 16 */
+ 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;
struct encoder_data_s {
- encoder_type type;
- int (*on_update_format)(dxr3_driver_t *);
- int (*on_frame_copy)(dxr3_driver_t *, dxr3_frame_t *, uint8_t **src);
- int (*on_display_frame)(dxr3_driver_t *, dxr3_frame_t *);
- int (*on_close)(dxr3_driver_t *);
+ encoder_type type;
+ int (*on_update_format)(dxr3_driver_t *);
+ int (*on_frame_copy)(dxr3_driver_t *, dxr3_frame_t *, uint8_t **src);
+ int (*on_display_frame)(dxr3_driver_t *, dxr3_frame_t *);
+ int (*on_close)(dxr3_driver_t *);
};
/* func definitions */
@@ -172,9 +172,9 @@ int dxr3_overlay_set_mode(dxr3_overlay_t *this, int mode);
int dxr3_overlay_set_attributes(dxr3_overlay_t *this);
int dxr3_overlay_set_screen(dxr3_overlay_t *this);
int dxr3_overlay_set_window(dxr3_overlay_t *this,
- int xpos, int ypos, int width, int height);
+ int xpos, int ypos, int width, int height);
void dxr3_overlay_adapt_area(dxr3_driver_t *this,
- int xpos, int ypos, int width, int height);
+ int xpos, int ypos, int width, int height);
void dxr3_overlay_update(dxr3_driver_t *this);
void dxr3_overlay_buggy_preinit(dxr3_overlay_t *this, int fd);
int dxr3_overlay_read_state(dxr3_overlay_t *this);
diff --git a/src/dxr3/dxr3_vo_core.c b/src/dxr3/dxr3_vo_core.c
index a7bc04e50..dbcd96316 100644
--- a/src/dxr3/dxr3_vo_core.c
+++ b/src/dxr3/dxr3_vo_core.c
@@ -17,26 +17,26 @@
* 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.20 2002/04/03 09:40:40 mlampard Exp $
+ * $Id: dxr3_vo_core.c,v 1.21 2002/05/06 11:26:37 jcdutton Exp $
*
*************************************************************************
* core functions common to both Standard and RT-Encoding vo plugins *
- * *
- * functions in this file (in order of appearance): * *
- * malloc_aligned *
- * dxr3_overlay_adapt_area *
- * dxr3_get_keycolor *
- * dxr3_read_config *
- * is_fullscreen *
- * dxr3_zoomTV *
- * dxr3_get_property *
- * dxr3_set_property *
- * dxr3_get_property_min_max *
- * dxr3_translate_gui2video *
- * dxr3_gui_data_exchange *
- * dxr3_gather_screen_vars *
- * *
- * and overlay specific functions formerly in overlay.c *
+ * *
+ * functions in this file (in order of appearance): * *
+ * malloc_aligned *
+ * dxr3_overlay_adapt_area *
+ * dxr3_get_keycolor *
+ * dxr3_read_config *
+ * is_fullscreen *
+ * dxr3_zoomTV *
+ * dxr3_get_property *
+ * dxr3_set_property *
+ * dxr3_get_property_min_max *
+ * dxr3_translate_gui2video *
+ * dxr3_gui_data_exchange *
+ * dxr3_gather_screen_vars *
+ * *
+ * and overlay specific functions formerly in overlay.c *
*************************************************************************/
#include "dxr3_video_out.h"
@@ -61,483 +61,483 @@ void *malloc_aligned (size_t alignment, size_t size, void **mem) {
/****** update the overlay window ******/
void dxr3_overlay_update(dxr3_driver_t *this)
{
- if(this->overlay_enabled) {
- int gui_win_x, gui_win_y, gypos,gxpos,gw,gh;
-
- this->frame_output_cb (this->user_data,
+ if(this->overlay_enabled) {
+ int gui_win_x, gui_win_y, gypos,gxpos,gw,gh;
+
+ this->frame_output_cb (this->user_data,
this->video_width, this->video_height,
&gxpos, &gypos, &gw, &gh,
&gui_win_x, &gui_win_y );
- if(this->xpos!=gxpos || this->ypos!=gypos ||
- this->width !=gw || this->height!=gh) {
- this->xpos=gxpos+1;
- this->ypos=gypos+1;
- this->width=gw;
- this->height=gh;
- dxr3_overlay_adapt_area(this, this->xpos, this->ypos, this->width, this->height);
- }
- }
+ if(this->xpos!=gxpos || this->ypos!=gypos ||
+ this->width !=gw || this->height!=gh) {
+ this->xpos=gxpos+1;
+ this->ypos=gypos+1;
+ this->width=gw;
+ this->height=gh;
+ dxr3_overlay_adapt_area(this, this->xpos, this->ypos, this->width, this->height);
+ }
+ }
}
/****** detect true window position and adapt overlay to it *******/
void dxr3_overlay_adapt_area(dxr3_driver_t *this,
- int dest_x, int dest_y, int dest_width, int dest_height)
+ int dest_x, int dest_y, int dest_width, int dest_height)
{
- XWindowAttributes a;
- Window junkwin;
- int rx, ry;
+ XWindowAttributes a;
+ Window junkwin;
+ int rx, ry;
- XLockDisplay(this->display);
+ XLockDisplay(this->display);
- XSetForeground(this->display, this->gc, this->color.pixel);
- XGetWindowAttributes(this->display, this->win, &a);
- XTranslateCoordinates (this->display, this->win, a.root,
- dest_x, dest_y, &rx, &ry, &junkwin);
+ XSetForeground(this->display, this->gc, this->color.pixel);
+ XGetWindowAttributes(this->display, this->win, &a);
+ XTranslateCoordinates (this->display, this->win, a.root,
+ dest_x, dest_y, &rx, &ry, &junkwin);
- XUnlockDisplay(this->display);
-
- this->xpos = rx; this->ypos = ry;
- this->width = dest_width; this->height = dest_height;
+ XUnlockDisplay(this->display);
+
+ this->xpos = rx; this->ypos = ry;
+ this->width = dest_width; this->height = dest_height;
- dxr3_overlay_set_window(&this->overlay, this->xpos, this->ypos,
- this->width, this->height);
+ dxr3_overlay_set_window(&this->overlay, this->xpos, this->ypos,
+ this->width, this->height);
}
/****** Allocate keycolor in the current palette ***********/
void dxr3_get_keycolor(dxr3_driver_t *this)
{
- this->color.red = ((this->overlay.colorkey >> 16) & 0xff) * 256;
- this->color.green = ((this->overlay.colorkey >> 8) & 0xff) * 256;
- this->color.blue = ((this->overlay.colorkey ) & 0xff) * 256;
+ this->color.red = ((this->overlay.colorkey >> 16) & 0xff) * 256;
+ this->color.green = ((this->overlay.colorkey >> 8) & 0xff) * 256;
+ this->color.blue = ((this->overlay.colorkey ) & 0xff) * 256;
- XAllocColor(this->display, DefaultColormap(this->display,0), &this->color);
+ XAllocColor(this->display, DefaultColormap(this->display,0), &this->color);
}
/******* Read dxr3 configuration data from ~/.xinerc **********
* overlay setup data is read from ~/.overlay/res* in the *
- * overlay section below *
- ***************************************************************/
+ * overlay section below *
+ ***************************************************************/
void dxr3_read_config(dxr3_driver_t *this, void * visual_gen)
{
- char* str;
- config_values_t *config=this->config;
-
- if (ioctl(this->fd_control, EM8300_IOCTL_GETBCS, &this->bcs))
- printf("dxr3_vo: cannot read bcs values (%s)\n",
- strerror(errno));
+ char* str;
+ config_values_t *config=this->config;
+
+ if (ioctl(this->fd_control, EM8300_IOCTL_GETBCS, &this->bcs))
+ printf("dxr3_vo: cannot read bcs values (%s)\n",
+ strerror(errno));
- this->bcs.contrast = config->register_range(config, "dxr3.contrast", this->bcs.contrast,100,900,"Dxr3: contrast control",NULL,NULL,NULL);
- this->bcs.saturation = config->register_range(config, "dxr3.saturation", this->bcs.saturation,100,900,"Dxr3: saturation control",NULL,NULL,NULL);
- this->bcs.brightness = config->register_range(config, "dxr3.brightness", this->bcs.brightness,100,900,"Dxr3: brightness control",NULL,NULL,NULL);
+ this->bcs.contrast = config->register_range(config, "dxr3.contrast", this->bcs.contrast,100,900,"Dxr3: contrast control",NULL,NULL,NULL);
+ this->bcs.saturation = config->register_range(config, "dxr3.saturation", this->bcs.saturation,100,900,"Dxr3: saturation control",NULL,NULL,NULL);
+ this->bcs.brightness = config->register_range(config, "dxr3.brightness", this->bcs.brightness,100,900,"Dxr3: brightness control",NULL,NULL,NULL);
- this->fullscreen_rectangle = config->register_bool(config, "dxr3.fullscreen_rectangle",0,"Dxr3: Fullscreen Rectangle Mode",NULL,NULL,NULL);
+ this->fullscreen_rectangle = config->register_bool(config, "dxr3.fullscreen_rectangle",0,"Dxr3: Fullscreen Rectangle Mode",NULL,NULL,NULL);
- this->vo_driver.set_property(&this->vo_driver,
- VO_PROP_ASPECT_RATIO, ASPECT_FULL);
+ this->vo_driver.set_property(&this->vo_driver,
+ VO_PROP_ASPECT_RATIO, ASPECT_FULL);
- str = config->register_string(config, "dxr3.videoout_mode", "tv", "Dxr3: videoout mode (tv or overlay)", NULL,NULL,NULL);
+ str = config->register_string(config, "dxr3.videoout_mode", "tv", "Dxr3: videoout mode (tv or overlay)", NULL,NULL,NULL);
printf("dxr3:overlaymode=%s\n",str);
- if (!strcasecmp(str, "tv")) {
- this->overlay_enabled=0;
- this->tv_switchable=0; /* don't allow on-the-fly switching */
- } else if (!strcasecmp(str, "overlay")) {
- this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
- printf("dxr3_vo: setting up overlay mode\n");
- gather_screen_vars(this, visual_gen);
- if (dxr3_overlay_read_state(&this->overlay) == 0) {
- this->overlay_enabled = 1;
- this->tv_switchable=1;
- str = config->register_string(config, "dxr3.keycolor", "0x80a040", "Dxr3: overlay colourkey value",NULL,NULL,NULL);
-
- sscanf(str, "%x", &this->overlay.colorkey);
-
- str = config->register_string(config, "dxr3.color_interval", "50.0", "Dxr3: overlay colourkey range","A greater value widens the search range for the overlay keycolor",NULL,NULL);
-
- sscanf(str, "%f", &this->overlay.color_interval);
- } else {
- printf("dxr3_vo: please run autocal, overlay disabled\n");
- this->overlay_enabled=0;
- this->tv_switchable=0;
- }
- }
- str = config->register_string(config, "dxr3.preferred_tvmode", "default", "Dxr3 preferred tv mode - PAL, PAL60, NTSC or default",NULL,NULL,NULL);
-
- if (!strcasecmp(str, "ntsc")) {
- this->tv_mode = EM8300_VIDEOMODE_NTSC;
- printf("dxr3_vo: setting tv_mode to NTSC\n");
- } else if (!strcasecmp(str, "pal")) {
- this->tv_mode = EM8300_VIDEOMODE_PAL;
- printf("dxr3_vo: setting tv_mode to PAL 50Hz\n");
- } else if (!strcasecmp(str, "pal60")) {
- this->tv_mode = EM8300_VIDEOMODE_PAL60;
- printf("dxr3_vo: setting tv_mode to PAL 60Hz\n");
- } else {
- this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
- }
-
-
- if (this->tv_mode != EM8300_VIDEOMODE_DEFAULT)
- if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode))
- printf("dxr3_vo: setting video mode failed.");
+ if (!strcasecmp(str, "tv")) {
+ this->overlay_enabled=0;
+ this->tv_switchable=0; /* don't allow on-the-fly switching */
+ } else if (!strcasecmp(str, "overlay")) {
+ this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
+ printf("dxr3_vo: setting up overlay mode\n");
+ gather_screen_vars(this, visual_gen);
+ if (dxr3_overlay_read_state(&this->overlay) == 0) {
+ this->overlay_enabled = 1;
+ this->tv_switchable=1;
+ str = config->register_string(config, "dxr3.keycolor", "0x80a040", "Dxr3: overlay colourkey value",NULL,NULL,NULL);
+
+ sscanf(str, "%x", &this->overlay.colorkey);
+
+ str = config->register_string(config, "dxr3.color_interval", "50.0", "Dxr3: overlay colourkey range","A greater value widens the search range for the overlay keycolor",NULL,NULL);
+
+ sscanf(str, "%f", &this->overlay.color_interval);
+ } else {
+ printf("dxr3_vo: please run autocal, overlay disabled\n");
+ this->overlay_enabled=0;
+ this->tv_switchable=0;
+ }
+ }
+ str = config->register_string(config, "dxr3.preferred_tvmode", "default", "Dxr3 preferred tv mode - PAL, PAL60, NTSC or default",NULL,NULL,NULL);
+
+ if (!strcasecmp(str, "ntsc")) {
+ this->tv_mode = EM8300_VIDEOMODE_NTSC;
+ printf("dxr3_vo: setting tv_mode to NTSC\n");
+ } else if (!strcasecmp(str, "pal")) {
+ this->tv_mode = EM8300_VIDEOMODE_PAL;
+ printf("dxr3_vo: setting tv_mode to PAL 50Hz\n");
+ } else if (!strcasecmp(str, "pal60")) {
+ this->tv_mode = EM8300_VIDEOMODE_PAL60;
+ printf("dxr3_vo: setting tv_mode to PAL 60Hz\n");
+ } else {
+ this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
+ }
+
+
+ if (this->tv_mode != EM8300_VIDEOMODE_DEFAULT)
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode))
+ printf("dxr3_vo: setting video mode failed.");
}
/******** is this window fullscreen? ************/
int is_fullscreen(dxr3_driver_t *this)
{
- XWindowAttributes a;
-
- XGetWindowAttributes(this->display, this->win, &a);
- /* this is a good place for gathering the with and height
- * although it is a mis-use for is_fullscreen */
- this->width = a.width;
- this->height = a.height;
-
- return a.x==0 && a.y==0 &&
- a.width == this->overlay.screen_xres &&
- a.height == this->overlay.screen_yres;
+ XWindowAttributes a;
+
+ XGetWindowAttributes(this->display, this->win, &a);
+ /* this is a good place for gathering the with and height
+ * although it is a mis-use for is_fullscreen */
+ this->width = a.width;
+ this->height = a.height;
+
+ return a.x==0 && a.y==0 &&
+ a.width == this->overlay.screen_xres &&
+ a.height == this->overlay.screen_yres;
}
/******* Experimental zoom function for tvout only *********
- * (mis)uses the dxr3 dicom function *
+ * (mis)uses the dxr3 dicom function *
***********************************************************/
static void dxr3_zoomTV(dxr3_driver_t *this)
{
- em8300_register_t frame, visible, update;
- frame.microcode_register=1; /* Yes, this is a MC Reg */
- visible.microcode_register=1; /* Yes, this is a MC Reg */
- update.microcode_register=1;
-
- /* change left <- */
- frame.microcode_register=1; /* Yes, this is a MC Reg */
- visible.microcode_register=1; /* Yes, this is a MC Reg */
- frame.reg = 93; // dicom frame left
- visible.reg = 97; //dicom visible left
- update.reg = 65; //dicom_update
- update.val=1;
- frame.val=0x10;
- visible.val=0x10;
-
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame);
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible);
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update);
-
- /* change right -> */
- frame.microcode_register=1; /* Yes, this is a MC Reg */
- visible.microcode_register=1; /* Yes, this is a MC Reg */
- update.reg = 94; // dicom frame right
- visible.reg = 98; //dicom visible right
- update.reg = 65; //dicom_update
- update.val=1;
- frame.val=0x10;
- visible.val= 968;
-
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame);
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible);
- ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update);
+ em8300_register_t frame, visible, update;
+ frame.microcode_register=1; /* Yes, this is a MC Reg */
+ visible.microcode_register=1; /* Yes, this is a MC Reg */
+ update.microcode_register=1;
+
+ /* change left <- */
+ frame.microcode_register=1; /* Yes, this is a MC Reg */
+ visible.microcode_register=1; /* Yes, this is a MC Reg */
+ frame.reg = 93; // dicom frame left
+ visible.reg = 97; //dicom visible left
+ update.reg = 65; //dicom_update
+ update.val=1;
+ frame.val=0x10;
+ visible.val=0x10;
+
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame);
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible);
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update);
+
+ /* change right -> */
+ frame.microcode_register=1; /* Yes, this is a MC Reg */
+ visible.microcode_register=1; /* Yes, this is a MC Reg */
+ update.reg = 94; // dicom frame right
+ visible.reg = 98; //dicom visible right
+ update.reg = 65; //dicom_update
+ update.val=1;
+ frame.val=0x10;
+ visible.val= 968;
+
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame);
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible);
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update);
}
int dxr3_get_property (vo_driver_t *this_gen, int property)
{
- dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
- int val=0;
-
- switch (property) {
- case VO_PROP_SATURATION:
- val = this->bcs.saturation;
- break;
-
- case VO_PROP_CONTRAST:
- val = this->bcs.contrast;
- break;
-
- case VO_PROP_BRIGHTNESS:
- val = this->bcs.brightness;
- break;
-
- case VO_PROP_ASPECT_RATIO:
- val = this->aspectratio;
- break;
-
- case VO_PROP_COLORKEY:
- val = this->overlay.colorkey;
- break;
- case VO_PROP_ZOOM_FACTOR:
- case VO_PROP_TVMODE:
- break;
-
- case VO_PROP_VO_TYPE:
- val = VO_TYPE_DXR3;
- break;
- default:
- val = 0;
- printf("dxr3_vo: property %d not implemented!\n", property);
- }
-
- return val;
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ int val=0;
+
+ switch (property) {
+ case VO_PROP_SATURATION:
+ val = this->bcs.saturation;
+ break;
+
+ case VO_PROP_CONTRAST:
+ val = this->bcs.contrast;
+ break;
+
+ case VO_PROP_BRIGHTNESS:
+ val = this->bcs.brightness;
+ break;
+
+ case VO_PROP_ASPECT_RATIO:
+ val = this->aspectratio;
+ break;
+
+ case VO_PROP_COLORKEY:
+ val = this->overlay.colorkey;
+ break;
+ case VO_PROP_ZOOM_FACTOR:
+ case VO_PROP_TVMODE:
+ break;
+
+ case VO_PROP_VO_TYPE:
+ val = VO_TYPE_DXR3;
+ break;
+ default:
+ val = 0;
+ printf("dxr3_vo: property %d not implemented!\n", property);
+ }
+
+ return val;
}
int dxr3_set_property (vo_driver_t *this_gen,
- int property, int value)
+ int property, int value)
{
- dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
- int val, bcs_changed = 0;
- int fullscreen;
-
- switch (property) {
- case VO_PROP_SATURATION:
- this->bcs.saturation = value;
- bcs_changed = 1;
- break;
- case VO_PROP_CONTRAST:
- this->bcs.contrast = value;
- bcs_changed = 1;
- break;
- case VO_PROP_BRIGHTNESS:
- this->bcs.brightness = value;
- bcs_changed = 1;
- break;
- case VO_PROP_ASPECT_RATIO:
- /* xitk-ui just increments the value, so we make
- * just a two value "loop"
- */
- if (value > ASPECT_FULL)
- value = ASPECT_ANAMORPHIC;
- this->aspectratio = value;
- fullscreen = this->overlay_enabled ? is_fullscreen(this) : 0;
-
- if (value == ASPECT_ANAMORPHIC) {
- printf("dxr3_vo: setting aspect ratio to anamorphic\n");
- if (!this->overlay_enabled || fullscreen)
- val = EM8300_ASPECTRATIO_16_9;
- else /* The overlay window can adapt to the ratio */
- val = EM8300_ASPECTRATIO_4_3;
- this->desired_ratio = 16.0/9.0;
- } else {
- printf("dxr3_vo: setting aspect ratio to full\n");
- val = EM8300_ASPECTRATIO_4_3;
- this->desired_ratio = 4.0/3.0;
- }
-
- if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
- printf("dxr3_vo: failed to set aspect ratio (%s)\n",
- strerror(errno));
-
- if (this->overlay_enabled && !fullscreen){
- int foo;
- this->frame_output_cb(this->user_data, this->width,
- this->width/this->desired_ratio, &foo, &foo, &foo, &foo, &foo, &foo);
- }
- break;
- case VO_PROP_COLORKEY:
- printf("dxr3_vo: VO_PROP_COLORKEY not implemented!");
- this->overlay.colorkey = val;
- break;
- case VO_PROP_ZOOM_FACTOR: /* FIXME: Was ZOOM_X */
- if(!this->overlay_enabled){ /* TV-out only */
- if(value==1){
- printf("dxr3_vo: enabling 16:9 zoom\n");
- val=EM8300_ASPECTRATIO_4_3;
- if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
- printf("dxr3_vo: failed to set aspect ratio (%s)\n",
- strerror(errno));
- dxr3_zoomTV(this);
- }else if (value==-1){
- printf("dxr3_vo: disabling 16:9 zoom\n");
- if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &this->aspectratio))
- printf("dxr3_vo: failed to set aspect ratio (%s)\n",
- strerror(errno));
- }
- }
- break;
-
- case VO_PROP_TVMODE: {
- /* Use meta-v to cycle TV formats */
- static int newmode;
- newmode++;
- if (newmode>EM8300_VIDEOMODE_LAST)
- newmode=EM8300_VIDEOMODE_PAL;
- printf("dxr3_vo: Changing TVMode to ");
- if(newmode==EM8300_VIDEOMODE_PAL)
- printf("PAL\n");
- if(newmode==EM8300_VIDEOMODE_PAL60)
- printf("PAL60\n");
- if(newmode==EM8300_VIDEOMODE_NTSC)
- printf("NTSC\n");
- if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &newmode))
- printf("dxr3_vo: setting video mode failed.");
- }
- break;
- default:
- break;
- }
-
- if (bcs_changed){
- if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs))
- printf("dxr3_vo: bcs set failed (%s)\n",
- strerror(errno));
- this->config->update_num(this->config, "dxr3.contrast", this->bcs.contrast);
- this->config->update_num(this->config, "dxr3.saturation", this->bcs.saturation);
- this->config->update_num(this->config, "dxr3.brightness", this->bcs.brightness);
- }
-
- return value;
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ int val, bcs_changed = 0;
+ int fullscreen;
+
+ switch (property) {
+ case VO_PROP_SATURATION:
+ this->bcs.saturation = value;
+ bcs_changed = 1;
+ break;
+ case VO_PROP_CONTRAST:
+ this->bcs.contrast = value;
+ bcs_changed = 1;
+ break;
+ case VO_PROP_BRIGHTNESS:
+ this->bcs.brightness = value;
+ bcs_changed = 1;
+ break;
+ case VO_PROP_ASPECT_RATIO:
+ /* xitk-ui just increments the value, so we make
+ * just a two value "loop"
+ */
+ if (value > ASPECT_FULL)
+ value = ASPECT_ANAMORPHIC;
+ this->aspectratio = value;
+ fullscreen = this->overlay_enabled ? is_fullscreen(this) : 0;
+
+ if (value == ASPECT_ANAMORPHIC) {
+ printf("dxr3_vo: setting aspect ratio to anamorphic\n");
+ if (!this->overlay_enabled || fullscreen)
+ val = EM8300_ASPECTRATIO_16_9;
+ else /* The overlay window can adapt to the ratio */
+ val = EM8300_ASPECTRATIO_4_3;
+ this->desired_ratio = 16.0/9.0;
+ } else {
+ printf("dxr3_vo: setting aspect ratio to full\n");
+ val = EM8300_ASPECTRATIO_4_3;
+ this->desired_ratio = 4.0/3.0;
+ }
+
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
+ printf("dxr3_vo: failed to set aspect ratio (%s)\n",
+ strerror(errno));
+
+ if (this->overlay_enabled && !fullscreen){
+ int foo;
+ this->frame_output_cb(this->user_data, this->width,
+ this->width/this->desired_ratio, &foo, &foo, &foo, &foo, &foo, &foo);
+ }
+ break;
+ case VO_PROP_COLORKEY:
+ printf("dxr3_vo: VO_PROP_COLORKEY not implemented!");
+ this->overlay.colorkey = val;
+ break;
+ case VO_PROP_ZOOM_FACTOR: /* FIXME: Was ZOOM_X */
+ if(!this->overlay_enabled){ /* TV-out only */
+ if(value==1){
+ printf("dxr3_vo: enabling 16:9 zoom\n");
+ val=EM8300_ASPECTRATIO_4_3;
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
+ printf("dxr3_vo: failed to set aspect ratio (%s)\n",
+ strerror(errno));
+ dxr3_zoomTV(this);
+ }else if (value==-1){
+ printf("dxr3_vo: disabling 16:9 zoom\n");
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &this->aspectratio))
+ printf("dxr3_vo: failed to set aspect ratio (%s)\n",
+ strerror(errno));
+ }
+ }
+ break;
+
+ case VO_PROP_TVMODE: {
+ /* Use meta-v to cycle TV formats */
+ static int newmode;
+ newmode++;
+ if (newmode>EM8300_VIDEOMODE_LAST)
+ newmode=EM8300_VIDEOMODE_PAL;
+ printf("dxr3_vo: Changing TVMode to ");
+ if(newmode==EM8300_VIDEOMODE_PAL)
+ printf("PAL\n");
+ if(newmode==EM8300_VIDEOMODE_PAL60)
+ printf("PAL60\n");
+ if(newmode==EM8300_VIDEOMODE_NTSC)
+ printf("NTSC\n");
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &newmode))
+ printf("dxr3_vo: setting video mode failed.");
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (bcs_changed){
+ if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs))
+ printf("dxr3_vo: bcs set failed (%s)\n",
+ strerror(errno));
+ this->config->update_num(this->config, "dxr3.contrast", this->bcs.contrast);
+ this->config->update_num(this->config, "dxr3.saturation", this->bcs.saturation);
+ this->config->update_num(this->config, "dxr3.brightness", this->bcs.brightness);
+ }
+
+ return value;
}
void dxr3_get_property_min_max (vo_driver_t *this_gen,
- int property, int *min, int *max)
+ int property, int *min, int *max)
{
- /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
-
- switch (property) {
- case VO_PROP_SATURATION:
- case VO_PROP_CONTRAST:
- case VO_PROP_BRIGHTNESS:
- *min = 0;
- *max = 1000;
- break;
-
- default:
- *min = 0;
- *max = 0;
- }
+ /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
+
+ switch (property) {
+ case VO_PROP_SATURATION:
+ case VO_PROP_CONTRAST:
+ case VO_PROP_BRIGHTNESS:
+ *min = 0;
+ *max = 1000;
+ break;
+
+ default:
+ *min = 0;
+ *max = 0;
+ }
}
static void dxr3_translate_gui2video(dxr3_driver_t *this,
- int x, int y,
- int *vid_x, int *vid_y)
+ int x, int y,
+ int *vid_x, int *vid_y)
{
- x = x * this->video_width / this->width;
- y = y * this->video_height / this->height;
- *vid_x = x;
- *vid_y = y;
+ x = x * this->video_width / this->width;
+ y = y * this->video_height / this->height;
+ *vid_x = x;
+ *vid_y = y;
}
int dxr3_gui_data_exchange (vo_driver_t *this_gen,
- int data_type, void *data)
+ int data_type, void *data)
{
- dxr3_driver_t *this = (dxr3_driver_t*) this_gen;
+ dxr3_driver_t *this = (dxr3_driver_t*) this_gen;
-
- if (!this->overlay_enabled && !this->tv_switchable) return 0;
+
+ if (!this->overlay_enabled && !this->tv_switchable) return 0;
- switch (data_type) {
+ switch (data_type) {
/*************************************************************************
* FIXME: Removed due to changes in XV by Guenter, but don't know what to replace it with
- * Update 2/4/02 - Mike Lampard:
- * This functionality is now incorporated into dxr3_overlay_update until
+ * Update 2/4/02 - Mike Lampard:
+ * This functionality is now incorporated into dxr3_overlay_update until
* a cleaner way can be found to update window changes.
-
- case GUI_DATA_EX_DEST_POS_SIZE_CHANGED:{
- x11_rectangle_t *area = (x11_rectangle_t*) data;
- dxr3_overlay_adapt_area(this, area->x, area->y, area->w, area->h);
-
- if(is_fullscreen(this) && this->fullscreen_rectangle)
- dxr3_overlay_set_mode(&this->overlay,EM8300_OVERLAY_MODE_RECTANGLE);
- else if (this->fullscreen_rectangle)
- dxr3_overlay_set_mode(&this->overlay,EM8300_OVERLAY_MODE_OVERLAY);
- }
- break;
+
+ case GUI_DATA_EX_DEST_POS_SIZE_CHANGED:{
+ x11_rectangle_t *area = (x11_rectangle_t*) data;
+ dxr3_overlay_adapt_area(this, area->x, area->y, area->w, area->h);
+
+ if(is_fullscreen(this) && this->fullscreen_rectangle)
+ dxr3_overlay_set_mode(&this->overlay,EM8300_OVERLAY_MODE_RECTANGLE);
+ else if (this->fullscreen_rectangle)
+ dxr3_overlay_set_mode(&this->overlay,EM8300_OVERLAY_MODE_OVERLAY);
+ }
+ break;
*************************************************************************/
- case GUI_DATA_EX_EXPOSE_EVENT:{
- XLockDisplay(this->display);
- XFillRectangle(this->display, this->win,
- this->gc, 0, 0, this->width, this->height);
- XUnlockDisplay(this->display);
- dxr3_overlay_update(this);
- }
- break;
- case GUI_DATA_EX_DRAWABLE_CHANGED:{
- XWindowAttributes a;
- this->win = (Drawable) data;
- this->gc = XCreateGC(this->display, this->win, 0, NULL);
- XGetWindowAttributes(this->display, this->win, &a);
- dxr3_set_property((vo_driver_t*) this,
- VO_PROP_ASPECT_RATIO, this->aspectratio);
- }
- break;
- case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO:{
- int x1, y1, x2, y2;
- x11_rectangle_t *rect = data;
-
- dxr3_translate_gui2video(this, rect->x, rect->y,
- &x1, &y1);
- dxr3_translate_gui2video(this, rect->w, rect->h,
- &x2, &y2);
- rect->x = x1;
- rect->y = y1;
- rect->w = x2-x1;
- rect->h = y2-y1;
- }
- break;
- case GUI_DATA_EX_VIDEOWIN_VISIBLE:{
- int window_showing;
- (int *)window_showing = (int *)data;
- if(!window_showing){
- printf("dxr3_vo: Hiding VO window and diverting video to TV\n");
- dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF );
- this->overlay_enabled=0;
- }else{
- printf("dxr3_vo: Using VO window for overlaying video\n");
- dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OVERLAY );
- this->overlay_enabled=1;
- }
- dxr3_set_property((vo_driver_t*) this,
- VO_PROP_ASPECT_RATIO, this->aspectratio);
- break;
- }
-
- default:
- return -1;
- }
- return 0;
+ case GUI_DATA_EX_EXPOSE_EVENT:{
+ XLockDisplay(this->display);
+ XFillRectangle(this->display, this->win,
+ this->gc, 0, 0, this->width, this->height);
+ XUnlockDisplay(this->display);
+ dxr3_overlay_update(this);
+ }
+ break;
+ case GUI_DATA_EX_DRAWABLE_CHANGED:{
+ XWindowAttributes a;
+ this->win = (Drawable) data;
+ this->gc = XCreateGC(this->display, this->win, 0, NULL);
+ XGetWindowAttributes(this->display, this->win, &a);
+ dxr3_set_property((vo_driver_t*) this,
+ VO_PROP_ASPECT_RATIO, this->aspectratio);
+ }
+ break;
+ case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO:{
+ int x1, y1, x2, y2;
+ x11_rectangle_t *rect = data;
+
+ dxr3_translate_gui2video(this, rect->x, rect->y,
+ &x1, &y1);
+ dxr3_translate_gui2video(this, rect->w, rect->h,
+ &x2, &y2);
+ rect->x = x1;
+ rect->y = y1;
+ rect->w = x2-x1;
+ rect->h = y2-y1;
+ }
+ break;
+ case GUI_DATA_EX_VIDEOWIN_VISIBLE:{
+ int window_showing;
+ (int *)window_showing = (int *)data;
+ if(!window_showing){
+ printf("dxr3_vo: Hiding VO window and diverting video to TV\n");
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF );
+ this->overlay_enabled=0;
+ }else{
+ printf("dxr3_vo: Using VO window for overlaying video\n");
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OVERLAY );
+ this->overlay_enabled=1;
+ }
+ dxr3_set_property((vo_driver_t*) this,
+ VO_PROP_ASPECT_RATIO, this->aspectratio);
+ break;
+ }
+
+ default:
+ return -1;
+ }
+ return 0;
}
/******** detect screen resolution and colour depth **********/
void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis)
{
- int scrn;
+ int scrn;
#ifdef HAVE_XINERAMA
- int screens;
- int dummy_a, dummy_b;
- XineramaScreenInfo *screeninfo = NULL;
+ int screens;
+ int dummy_a, dummy_b;
+ XineramaScreenInfo *screeninfo = NULL;
#endif
- this->win = vis->d;
- this->display = vis->display;
- this->user_data = vis->user_data;
- this->gc = XCreateGC(this->display, this->win, 0, NULL);
- scrn = DefaultScreen(this->display);
+ this->win = vis->d;
+ this->display = vis->display;
+ this->user_data = vis->user_data;
+ this->gc = XCreateGC(this->display, this->win, 0, NULL);
+ scrn = DefaultScreen(this->display);
- /* Borrowed from xine-ui in order to detect fullscreen */
+ /* Borrowed from xine-ui in order to detect fullscreen */
#ifdef HAVE_XINERAMA
- if (XineramaQueryExtension(this->display, &dummy_a, &dummy_b) &&
- (screeninfo = XineramaQueryScreens(this->display, &screens)) &&
- XineramaIsActive(this->display))
- {
- this->overlay.screen_xres = screeninfo[0].width;
- this->overlay.screen_yres = screeninfo[0].height;
- } else
+ if (XineramaQueryExtension(this->display, &dummy_a, &dummy_b) &&
+ (screeninfo = XineramaQueryScreens(this->display, &screens)) &&
+ XineramaIsActive(this->display))
+ {
+ this->overlay.screen_xres = screeninfo[0].width;
+ this->overlay.screen_yres = screeninfo[0].height;
+ } else
#endif
- {
- this->overlay.screen_xres = DisplayWidth(this->display, scrn);
- this->overlay.screen_yres = DisplayHeight(this->display, scrn);
- }
+ {
+ this->overlay.screen_xres = DisplayWidth(this->display, scrn);
+ this->overlay.screen_yres = DisplayHeight(this->display, scrn);
+ }
- this->overlay.screen_depth = DisplayPlanes(this->display, scrn);
- this->frame_output_cb = (void *)vis->frame_output_cb;
+ this->overlay.screen_depth = DisplayPlanes(this->display, scrn);
+ this->frame_output_cb = (void *)vis->frame_output_cb;
/* request_dest_size; */
- printf("xres %d yres %d depth %d\n", this->overlay.screen_xres, this->overlay.screen_yres, this->overlay.screen_depth);
+ printf("xres %d yres %d depth %d\n", this->overlay.screen_xres, this->overlay.screen_yres, this->overlay.screen_depth);
}
/**************************************************************************
- * Overlay initialisation and other overlay_specific functions *
+ * Overlay initialisation and other overlay_specific functions *
**************************************************************************/
#define TYPE_INT 1
@@ -553,249 +553,249 @@ struct lut_entry {
static struct lut_entry *new_lookuptable(dxr3_overlay_t *this)
{
- struct lut_entry m[] = {
- {"xoffset", TYPE_INT, &this->xoffset},
- {"yoffset", TYPE_INT, &this->yoffset},
- {"xcorr", TYPE_INT, &this->xcorr},
- {"jitter", TYPE_INT, &this->jitter},
- {"stability", TYPE_INT, &this->stability},
- {"keycolor", TYPE_XINT, &this->colorkey},
- {"colcal_upper", TYPE_COEFF, &this->colcal_upper[0]},
- {"colcal_lower", TYPE_COEFF, &this->colcal_lower[0]},
- {"color_interval", TYPE_FLOAT, &this->color_interval},
- {0,0,0}
- },*p;
-
- p = malloc(sizeof(m));
- memcpy(p,m,sizeof(m));
- return p;
+ struct lut_entry m[] = {
+ {"xoffset", TYPE_INT, &this->xoffset},
+ {"yoffset", TYPE_INT, &this->yoffset},
+ {"xcorr", TYPE_INT, &this->xcorr},
+ {"jitter", TYPE_INT, &this->jitter},
+ {"stability", TYPE_INT, &this->stability},
+ {"keycolor", TYPE_XINT, &this->colorkey},
+ {"colcal_upper", TYPE_COEFF, &this->colcal_upper[0]},
+ {"colcal_lower", TYPE_COEFF, &this->colcal_lower[0]},
+ {"color_interval", TYPE_FLOAT, &this->color_interval},
+ {0,0,0}
+ },*p;
+
+ p = malloc(sizeof(m));
+ memcpy(p,m,sizeof(m));
+ return p;
}
static int lookup_parameter(struct lut_entry *lut, char *name,
void **ptr, int *type)
{
- int i;
- for(i=0; lut[i].name; i++)
- if(!strcmp(name,lut[i].name)) {
- *ptr = lut[i].ptr;
- *type = lut[i].type;
+ int i;
+ for(i=0; lut[i].name; i++)
+ if(!strcmp(name,lut[i].name)) {
+ *ptr = lut[i].ptr;
+ *type = lut[i].type;
#if OVERLAY_LOG
- printf("dxr3: found parameter \"%s\"\n", name);
+ printf("dxr3: found parameter \"%s\"\n", name);
#endif
- return 1;
- }
+ return 1;
+ }
#if OVERLAY_LOG
- printf("dxr3: WARNING: unknown parameter \"%s\"\n", name);
+ printf("dxr3: WARNING: unknown parameter \"%s\"\n", name);
#endif
- return 0;
+ return 0;
}
int dxr3_overlay_read_state(dxr3_overlay_t *this)
{
- char *tok;
- char fname[128],tmp[128],line[256];
- FILE *fp;
- struct lut_entry *lut;
- void *ptr;
- int type;
- int j;
- char *loc;
-
- /* store previous locale */
- loc = setlocale(LC_NUMERIC, NULL);
- /* set american locale for floating point values
- * (used by .overlay/res file) */
- setlocale(LC_NUMERIC, "en_US");
-
- strcpy(fname,getenv("HOME"));
- strcat(fname,"/.overlay");
-
- sprintf(tmp,"/res_%dx%dx%d",
- this->screen_xres,this->screen_yres,this->screen_depth);
- strcat(fname,tmp);
+ char *tok;
+ char fname[128],tmp[128],line[256];
+ FILE *fp;
+ struct lut_entry *lut;
+ void *ptr;
+ int type;
+ int j;
+ char *loc;
+
+ /* store previous locale */
+ loc = setlocale(LC_NUMERIC, NULL);
+ /* set american locale for floating point values
+ * (used by .overlay/res file) */
+ setlocale(LC_NUMERIC, "en_US");
+
+ strcpy(fname,getenv("HOME"));
+ strcat(fname,"/.overlay");
+
+ sprintf(tmp,"/res_%dx%dx%d",
+ this->screen_xres,this->screen_yres,this->screen_depth);
+ strcat(fname,tmp);
#if OVERLAY_LOG
- printf("dxr3: attempting to open %s\n", fname);
+ printf("dxr3: attempting to open %s\n", fname);
#endif
- if(!(fp=fopen(fname,"r"))){
- printf("ERRROR Reading overlay init file!! run autocal !!!\n");
- return -1;
- }
-
- lut = new_lookuptable(this);
-
- while(!feof(fp)) {
- if(!fgets(line,256,fp))
- break;
- tok=strtok(line," ");
- if(lookup_parameter(lut,tok,&ptr,&type)) {
- tok=strtok(NULL," \n");
- switch(type) {
- case TYPE_INT:
- sscanf(tok,"%d",(int *)ptr);
+ if(!(fp=fopen(fname,"r"))){
+ printf("ERRROR Reading overlay init file!! run autocal !!!\n");
+ return -1;
+ }
+
+ lut = new_lookuptable(this);
+
+ while(!feof(fp)) {
+ if(!fgets(line,256,fp))
+ break;
+ tok=strtok(line," ");
+ if(lookup_parameter(lut,tok,&ptr,&type)) {
+ tok=strtok(NULL," \n");
+ switch(type) {
+ case TYPE_INT:
+ sscanf(tok,"%d",(int *)ptr);
#if OVERLAY_LOG
- printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr);
+ printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr);
#endif
- break;
- case TYPE_XINT:
- sscanf(tok,"%x",(int *)ptr);
+ break;
+ case TYPE_XINT:
+ sscanf(tok,"%x",(int *)ptr);
#if OVERLAY_LOG
- printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr);
+ printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr);
#endif
- break;
- case TYPE_FLOAT:
- sscanf(tok,"%f",(float *)ptr);
+ break;
+ case TYPE_FLOAT:
+ sscanf(tok,"%f",(float *)ptr);
#if OVERLAY_LOG
- printf("dxr3: value \"%s\" -> %f\n", tok, *(float*)ptr);
+ printf("dxr3: value \"%s\" -> %f\n", tok, *(float*)ptr);
#endif
- break;
- case TYPE_COEFF:
- for(j=0;j<3;j++) {
- sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
+ break;
+ case TYPE_COEFF:
+ for(j=0;j<3;j++) {
+ sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
#if OVERLAY_LOG
- printf("dxr3: value (%d,k) \"%s\" -> %f\n", j, tok, ((struct coeff*)ptr)[j].k);
+ printf("dxr3: value (%d,k) \"%s\" -> %f\n", j, tok, ((struct coeff*)ptr)[j].k);
#endif
- tok=strtok(NULL," \n");
- sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
+ tok=strtok(NULL," \n");
+ sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
#if OVERLAY_LOG
- printf("dxr3: value (%d,m) \"%s\" -> %f\n", j, tok, ((struct coeff*)ptr)[j].m);
+ printf("dxr3: value (%d,m) \"%s\" -> %f\n", j, tok, ((struct coeff*)ptr)[j].m);
#endif
- tok=strtok(NULL," \n");
- }
- break;
- }
- }
- }
- free(lut);
- fclose(fp);
- /* restore original locale */
- setlocale(LC_NUMERIC, loc);
- return 0;
+ tok=strtok(NULL," \n");
+ }
+ break;
+ }
+ }
+ }
+ free(lut);
+ fclose(fp);
+ /* restore original locale */
+ setlocale(LC_NUMERIC, loc);
+ return 0;
}
static int col_interp(float x, struct coeff c)
{
- int y;
- y = rint(x*c.k + c.m);
- if (y > 255) y = 255;
- if (y < 0) y = 0;
- return y;
+ int y;
+ y = rint(x*c.k + c.m);
+ if (y > 255) y = 255;
+ if (y < 0) y = 0;
+ return y;
}
int dxr3_overlay_set_keycolor(dxr3_overlay_t *this)
{
- float r = (this->colorkey & 0xff0000) >> 16;
- float g = (this->colorkey & 0x00ff00) >> 8;
- float b = (this->colorkey & 0x0000ff);
- float interval = this->color_interval;
- int ret;
- int32_t overlay_limit;
- em8300_attribute_t attr;
+ float r = (this->colorkey & 0xff0000) >> 16;
+ float g = (this->colorkey & 0x00ff00) >> 8;
+ float b = (this->colorkey & 0x0000ff);
+ float interval = this->color_interval;
+ int ret;
+ int32_t overlay_limit;
+ em8300_attribute_t attr;
#if OVERLAY_LOG
- printf("dxr3: set_keycolor: r=%f g=%f b=%f, interval = %f\n",
- r,g,b,interval);
+ printf("dxr3: set_keycolor: r=%f g=%f b=%f, interval = %f\n",
+ r,g,b,interval);
#endif
- overlay_limit = /* lower limit */
- col_interp(r - interval, this->colcal_lower[0]) << 16 |
- col_interp(g - interval, this->colcal_lower[1]) << 8 |
- col_interp(b - interval, this->colcal_lower[2]);
+ overlay_limit = /* lower limit */
+ col_interp(r - interval, this->colcal_lower[0]) << 16 |
+ col_interp(g - interval, this->colcal_lower[1]) << 8 |
+ col_interp(b - interval, this->colcal_lower[2]);
#if OVERLAY_LOG
- printf("dxr3: lower overlay_limit = %d\n", overlay_limit);
+ printf("dxr3: lower overlay_limit = %d\n", overlay_limit);
#endif
- attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_LOWER;
- attr.value = overlay_limit;
- ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
- if (ret < 0) {
- printf("dxr3: WARNING: error setting overlay upperl limit attribute\n");
- return ret;
- }
-
- overlay_limit = /* upper limit */
- col_interp(r + interval, this->colcal_upper[0]) << 16 |
- col_interp(g + interval, this->colcal_upper[1]) << 8 |
- col_interp(b + interval, this->colcal_upper[2]);
+ attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_LOWER;
+ attr.value = overlay_limit;
+ ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
+ if (ret < 0) {
+ printf("dxr3: WARNING: error setting overlay upperl limit attribute\n");
+ return ret;
+ }
+
+ overlay_limit = /* upper limit */
+ col_interp(r + interval, this->colcal_upper[0]) << 16 |
+ col_interp(g + interval, this->colcal_upper[1]) << 8 |
+ col_interp(b + interval, this->colcal_upper[2]);
#if OVERLAY_LOG
- printf("dxr3: upper overlay_limit = %d\n", overlay_limit);
+ printf("dxr3: upper overlay_limit = %d\n", overlay_limit);
#endif
- attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_UPPER;
- attr.value = overlay_limit;
- ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
- if (ret < 0) {
- printf("dxr3: WARNING: error setting overlay upperl limit attribute\n");
- }
- return ret;
+ attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_UPPER;
+ attr.value = overlay_limit;
+ ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
+ if (ret < 0) {
+ printf("dxr3: WARNING: error setting overlay upperl limit attribute\n");
+ }
+ return ret;
}
int dxr3_overlay_set_mode(dxr3_overlay_t *this, int mode)
{
- return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &mode);
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &mode);
}
int dxr3_overlay_set_attributes(dxr3_overlay_t *this)
{
- em8300_attribute_t attr;
- attr.attribute = EM9010_ATTRIBUTE_XOFFSET;
- attr.value = this->xoffset;
- if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
- return -1;
- attr.attribute = EM9010_ATTRIBUTE_YOFFSET;
- attr.value = this->yoffset;
- if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
- return -1;
- attr.attribute = EM9010_ATTRIBUTE_XCORR;
- attr.value = this->xcorr;
- if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
- return -1;
- attr.attribute = EM9010_ATTRIBUTE_STABILITY;
- attr.value = this->stability;
- if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
- return -1;
- attr.attribute = EM9010_ATTRIBUTE_JITTER;
- attr.value = this->jitter;
- return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
+ em8300_attribute_t attr;
+ attr.attribute = EM9010_ATTRIBUTE_XOFFSET;
+ attr.value = this->xoffset;
+ if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
+ return -1;
+ attr.attribute = EM9010_ATTRIBUTE_YOFFSET;
+ attr.value = this->yoffset;
+ if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
+ return -1;
+ attr.attribute = EM9010_ATTRIBUTE_XCORR;
+ attr.value = this->xcorr;
+ if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
+ return -1;
+ attr.attribute = EM9010_ATTRIBUTE_STABILITY;
+ attr.value = this->stability;
+ if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1)
+ return -1;
+ attr.attribute = EM9010_ATTRIBUTE_JITTER;
+ attr.value = this->jitter;
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
}
int dxr3_overlay_set_screen(dxr3_overlay_t *this)
{
- em8300_overlay_screen_t scr;
- scr.xsize = this->screen_xres;
- scr.ysize = this->screen_yres;
- return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr);
+ em8300_overlay_screen_t scr;
+ scr.xsize = this->screen_xres;
+ scr.ysize = this->screen_yres;
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr);
}
int dxr3_overlay_set_window(dxr3_overlay_t *this,
int xpos, int ypos, int width, int height)
{
- em8300_overlay_window_t win;
-
- /* is some part of the picture visible? */
- if (xpos+width < 0) return 0;
- if (ypos+height < 0) return 0;
- if (xpos > this->screen_xres) return 0;
- if (ypos > this->screen_yres) return 0;
-
- win.xpos = xpos;
- win.ypos = ypos;
- win.width = width;
- win.height = height;
- return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETWINDOW, &win);
+ em8300_overlay_window_t win;
+
+ /* is some part of the picture visible? */
+ if (xpos+width < 0) return 0;
+ if (ypos+height < 0) return 0;
+ if (xpos > this->screen_xres) return 0;
+ if (ypos > this->screen_yres) return 0;
+
+ win.xpos = xpos;
+ win.ypos = ypos;
+ win.width = width;
+ win.height = height;
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETWINDOW, &win);
}
int dxr3_overlay_set_signalmode(dxr3_overlay_t *this,int mode)
{
- return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode);
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode);
}
void dxr3_overlay_buggy_preinit(dxr3_overlay_t *this, int fd)
{
- /* TODO: catch errors */
-
- this->fd_control = fd;
- dxr3_overlay_set_screen(this);
- dxr3_overlay_set_window(this, 1,1, 2,2);
- dxr3_overlay_set_keycolor(this);
- dxr3_overlay_set_attributes(this);
- dxr3_overlay_set_mode(this, EM8300_OVERLAY_MODE_OVERLAY);
+ /* TODO: catch errors */
+
+ this->fd_control = fd;
+ dxr3_overlay_set_screen(this);
+ dxr3_overlay_set_window(this, 1,1, 2,2);
+ dxr3_overlay_set_keycolor(this);
+ dxr3_overlay_set_attributes(this);
+ dxr3_overlay_set_mode(this, EM8300_OVERLAY_MODE_OVERLAY);
}
diff --git a/src/dxr3/mpeg_encoders.c b/src/dxr3/mpeg_encoders.c
index 63bc3c729..841a9d8ae 100644
--- a/src/dxr3/mpeg_encoders.c
+++ b/src/dxr3/mpeg_encoders.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: mpeg_encoders.c,v 1.6 2002/03/31 14:33:12 mlampard Exp $
+ * $Id: mpeg_encoders.c,v 1.7 2002/05/06 11:26:37 jcdutton Exp $
*
* mpeg encoders for the dxr3 video out plugin.
*/
@@ -44,18 +44,18 @@
#ifdef HAVE_LIBRTE
typedef struct {
- encoder_data_t encoder_data;
- int width, height;
- rte_context* context; /* handle for encoding */
- void* rte_ptr; /* buffer maintened by librte */
- double rte_time; /* frame time (s) */
- double rte_time_step; /* time per frame (s) */
- double rte_bitrate; /* mpeg out bitrate, default 2.3e6 bits/s */
+ encoder_data_t encoder_data;
+ int width, height;
+ rte_context* context; /* handle for encoding */
+ void* rte_ptr; /* buffer maintened by librte */
+ double rte_time; /* frame time (s) */
+ double rte_time_step; /* time per frame (s) */
+ double rte_bitrate; /* mpeg out bitrate, default 2.3e6 bits/s */
} rte_data_t;
static void mp1e_callback(rte_context *context, void *data, ssize_t size,
- void* user_data)
+ void* user_data)
{
dxr3_driver_t *this = (dxr3_driver_t*)user_data;
em8300_register_t regs;
@@ -63,7 +63,7 @@ static void mp1e_callback(rte_context *context, void *data, ssize_t size,
if (this->enhanced_mode)
{
- regs.microcode_register=1; /* Yes, this is a MC Reg */
+ regs.microcode_register=1; /* Yes, this is a MC Reg */
regs.reg = MV_COMMAND;
regs.val=6; /* Mike's mystery number :-) */
ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &regs);
@@ -80,164 +80,164 @@ static void mp1e_callback(rte_context *context, void *data, ssize_t size,
static int rte_on_update_format(dxr3_driver_t *drv)
{
- rte_data_t *this = (rte_data_t*)drv->enc;
- rte_context* context;
- rte_codec *codec;
- int width, height;
- char tmpstr[128];
-
- width = drv->video_width;
- height = drv->video_height;
-
- if (this->context != 0) {/* already running */
- printf("dxr3: closing current encoding context.\n");
- rte_stop(this->context);
- rte_context_delete(this->context);
- this->context = 0;
- }
- this->width = width;
- this->height = height;
-
- this->context = rte_context_new (width, height, "mp1e", drv);
- if (! this->context) {
- printf("dxr3: failed to get rte context.\n");
- return 1;
- }
- context = this->context; /* shortcut */
- rte_set_verbosity(context, 2);
- /* get mpeg codec handle */
- codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1_video");
- if (! codec) {
- printf("dxr3: could not create codec.\n");
- rte_context_destroy(context);
- context = 0;
- return 1;
- }
- this->rte_bitrate=drv->config->register_range(drv->config,"dxr3.rte_bitrate",10000, 1000,20000, "Dxr3enc: rte mpeg output bitrate (kbit/s)",NULL,NULL,NULL);
- this->rte_bitrate *= 1000; /* config in kbit/s, rte wants bit/s */
- /* FIXME: this needs to be replaced with a codec option call.
- * However, there seems to be none for the colour format!
- * So we'll use the deprecated set_video_parameters instead.
- * Alternative is to manually set context->video_format (RTE_YU... )
- * and context->video_bytes (= width * height * bytes/pixel) */
- rte_set_video_parameters(context,
- (drv->format == IMGFMT_YV12 ? RTE_YUV420 : RTE_YUYV),
- context->width, context->height,
- context->video_rate, context->output_video_bits,
- context->gop_sequence);
- /* Now set a whole bunch of codec options */
- /* If I understand correctly, virtual_frame_rate is the frame rate
- * of the source (can be anything), while coded_frame_rate must be
- * one of the mpeg1 alloweds */
- if (!rte_option_set(codec, "virtual_frame_rate", drv->fps))
- printf("dxr3: WARNING: rte_option_set failed; virtual_frame_rate=%g.\n",drv->fps);
- if (!rte_option_set(codec, "coded_frame_rate", drv->fps))
- printf("dxr3: WARNING: rte_option_set failed; coded_frame_rate=%g.\n",drv->fps);
- if (!rte_option_set(codec, "bit_rate", (int)this->rte_bitrate))
- printf("dxr3: WARNING: rte_option_set failed; bit_rate = %d.\n",
- (int)this->rte_bitrate);
- if (!rte_option_set(codec, "gop_sequence", "I"))
- printf("dxr3: WARNING: rte_option_set failed; gop_sequence = \"I\".\n");
- /* just to be sure, disable motion comp (not needed in I frames) */
- if (!rte_option_set(codec, "motion_compensation", 0))
- printf("dxr3: WARNING: rte_option_set failed; motion_compensation = 0.\n");
- rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL);
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv", drv->devname);
- rte_set_output(context, mp1e_callback, NULL, NULL);
- if (!rte_init_context(context)) {
- printf("dxr3: cannot init the context: %s\n",
- context->error);
- rte_context_delete(context);
- context = 0;
- return 1;
- }
- /* do the sync'ing and start encoding */
- if (!rte_start_encoding(context)) {
- printf("dxr3: cannot start encoding: %s\n",
- context->error);
- rte_context_delete(context);
- context = 0;
- return 1;
- }
- this->rte_ptr = rte_push_video_data(context, NULL, 0);
- if (! this->rte_ptr) {
- printf("dxr3: failed to get encoder buffer pointer.\n");
- return 1;
- }
- this->rte_time = 0.0;
- this->rte_time_step = 1.0/drv->fps;
-
- return 0;
+ rte_data_t *this = (rte_data_t*)drv->enc;
+ rte_context* context;
+ rte_codec *codec;
+ int width, height;
+ char tmpstr[128];
+
+ width = drv->video_width;
+ height = drv->video_height;
+
+ if (this->context != 0) {/* already running */
+ printf("dxr3: closing current encoding context.\n");
+ rte_stop(this->context);
+ rte_context_delete(this->context);
+ this->context = 0;
+ }
+ this->width = width;
+ this->height = height;
+
+ this->context = rte_context_new (width, height, "mp1e", drv);
+ if (! this->context) {
+ printf("dxr3: failed to get rte context.\n");
+ return 1;
+ }
+ context = this->context; /* shortcut */
+ rte_set_verbosity(context, 2);
+ /* get mpeg codec handle */
+ codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1_video");
+ if (! codec) {
+ printf("dxr3: could not create codec.\n");
+ rte_context_destroy(context);
+ context = 0;
+ return 1;
+ }
+ this->rte_bitrate=drv->config->register_range(drv->config,"dxr3.rte_bitrate",10000, 1000,20000, "Dxr3enc: rte mpeg output bitrate (kbit/s)",NULL,NULL,NULL);
+ this->rte_bitrate *= 1000; /* config in kbit/s, rte wants bit/s */
+ /* FIXME: this needs to be replaced with a codec option call.
+ * However, there seems to be none for the colour format!
+ * So we'll use the deprecated set_video_parameters instead.
+ * Alternative is to manually set context->video_format (RTE_YU... )
+ * and context->video_bytes (= width * height * bytes/pixel) */
+ rte_set_video_parameters(context,
+ (drv->format == IMGFMT_YV12 ? RTE_YUV420 : RTE_YUYV),
+ context->width, context->height,
+ context->video_rate, context->output_video_bits,
+ context->gop_sequence);
+ /* Now set a whole bunch of codec options */
+ /* If I understand correctly, virtual_frame_rate is the frame rate
+ * of the source (can be anything), while coded_frame_rate must be
+ * one of the mpeg1 alloweds */
+ if (!rte_option_set(codec, "virtual_frame_rate", drv->fps))
+ printf("dxr3: WARNING: rte_option_set failed; virtual_frame_rate=%g.\n",drv->fps);
+ if (!rte_option_set(codec, "coded_frame_rate", drv->fps))
+ printf("dxr3: WARNING: rte_option_set failed; coded_frame_rate=%g.\n",drv->fps);
+ if (!rte_option_set(codec, "bit_rate", (int)this->rte_bitrate))
+ printf("dxr3: WARNING: rte_option_set failed; bit_rate = %d.\n",
+ (int)this->rte_bitrate);
+ if (!rte_option_set(codec, "gop_sequence", "I"))
+ printf("dxr3: WARNING: rte_option_set failed; gop_sequence = \"I\".\n");
+ /* just to be sure, disable motion comp (not needed in I frames) */
+ if (!rte_option_set(codec, "motion_compensation", 0))
+ printf("dxr3: WARNING: rte_option_set failed; motion_compensation = 0.\n");
+ rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL);
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", drv->devname);
+ rte_set_output(context, mp1e_callback, NULL, NULL);
+ if (!rte_init_context(context)) {
+ printf("dxr3: cannot init the context: %s\n",
+ context->error);
+ rte_context_delete(context);
+ context = 0;
+ return 1;
+ }
+ /* do the sync'ing and start encoding */
+ if (!rte_start_encoding(context)) {
+ printf("dxr3: cannot start encoding: %s\n",
+ context->error);
+ rte_context_delete(context);
+ context = 0;
+ return 1;
+ }
+ this->rte_ptr = rte_push_video_data(context, NULL, 0);
+ if (! this->rte_ptr) {
+ printf("dxr3: failed to get encoder buffer pointer.\n");
+ return 1;
+ }
+ this->rte_time = 0.0;
+ this->rte_time_step = 1.0/drv->fps;
+
+ return 0;
}
static int rte_on_display_frame( dxr3_driver_t* drv, dxr3_frame_t* frame )
{
- int size;
- rte_data_t* this = (rte_data_t*)drv->enc;
-
- if ( (this->width != frame->width) || (this->height != frame->oheight)){
- /* maybe we were reinitialized and get an old frame. */
- return 0;
- }
- size = frame->width * frame->oheight;
- if (frame->vo_frame.format == IMGFMT_YV12)
- xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*3/2);
- else
- xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*2);
- this->rte_time += this->rte_time_step;
- this->rte_ptr = rte_push_video_data(this->context, this->rte_ptr,
- this->rte_time);
- frame->vo_frame.displayed(&frame->vo_frame);
- return 0;
+ int size;
+ rte_data_t* this = (rte_data_t*)drv->enc;
+
+ if ( (this->width != frame->width) || (this->height != frame->oheight)){
+ /* maybe we were reinitialized and get an old frame. */
+ return 0;
+ }
+ size = frame->width * frame->oheight;
+ if (frame->vo_frame.format == IMGFMT_YV12)
+ xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*3/2);
+ else
+ xine_fast_memcpy(this->rte_ptr, frame->real_base[0], size*2);
+ this->rte_time += this->rte_time_step;
+ this->rte_ptr = rte_push_video_data(this->context, this->rte_ptr,
+ this->rte_time);
+ frame->vo_frame.displayed(&frame->vo_frame);
+ return 0;
}
static int rte_on_close( dxr3_driver_t *drv )
{
- rte_data_t *this = (rte_data_t*)drv->enc;
- if (this->context) {
- rte_stop(this->context);
- rte_context_delete(this->context);
- this->context = 0;
- }
- free(this);
- drv->enc = 0;
- return 0;
+ rte_data_t *this = (rte_data_t*)drv->enc;
+ if (this->context) {
+ rte_stop(this->context);
+ rte_context_delete(this->context);
+ this->context = 0;
+ }
+ free(this);
+ drv->enc = 0;
+ return 0;
}
int dxr3_rte_init( dxr3_driver_t *drv )
{
- rte_data_t* this;
- if (! rte_init() ) {
- printf("dxr3: failed to init librte\n");
- return 1;
- }
- this = malloc(sizeof(rte_data_t));
- if (!this)
- return 1;
- memset(this, 0, sizeof(rte_data_t));
- this->encoder_data.type = ENC_RTE;
- this->context = 0;
- this->encoder_data.on_update_format = rte_on_update_format;
- this->encoder_data.on_frame_copy = 0;
- this->encoder_data.on_display_frame = rte_on_display_frame;
- this->encoder_data.on_close = rte_on_close;
- drv->enc = (encoder_data_t*)this;
- return 0;
+ rte_data_t* this;
+ if (! rte_init() ) {
+ printf("dxr3: failed to init librte\n");
+ return 1;
+ }
+ this = malloc(sizeof(rte_data_t));
+ if (!this)
+ return 1;
+ memset(this, 0, sizeof(rte_data_t));
+ this->encoder_data.type = ENC_RTE;
+ this->context = 0;
+ this->encoder_data.on_update_format = rte_on_update_format;
+ this->encoder_data.on_frame_copy = 0;
+ this->encoder_data.on_display_frame = rte_on_display_frame;
+ this->encoder_data.on_close = rte_on_close;
+ drv->enc = (encoder_data_t*)this;
+ return 0;
}
#endif
#ifdef HAVE_LIBFAME
typedef struct {
- encoder_data_t encoder_data;
- fame_context_t *fc; /* needed for fame calls */
- fame_parameters_t fp;
- fame_yuv_t yuv;
- /* temporary buffer for mpeg data */
- char *buffer;
- /* temporary buffer for YUY2->YV12 conversion */
- uint8_t *out[3]; /* aligned buffer for YV12 data */
- uint8_t *buf; /* unaligned YV12 buffer */
+ encoder_data_t encoder_data;
+ fame_context_t *fc; /* needed for fame calls */
+ fame_parameters_t fp;
+ fame_yuv_t yuv;
+ /* temporary buffer for mpeg data */
+ char *buffer;
+ /* temporary buffer for YUY2->YV12 conversion */
+ uint8_t *out[3]; /* aligned buffer for YV12 data */
+ uint8_t *buf; /* unaligned YV12 buffer */
} fame_data_t;
@@ -245,208 +245,208 @@ static fame_parameters_t dummy_init_fp = FAME_PARAMETERS_INITIALIZER;
static int fame_on_update_format(dxr3_driver_t *drv)
{
- fame_data_t *this = (fame_data_t*)drv->enc;
- double fps;
-
- /* if YUY2 and dimensions changed, we need to re-allocate the
- * internal YV12 buffer */
- if (this->buf) free(this->buf);
- this->buf = 0;
- this->out[0] = this->out[1] = this->out[2] = 0;
- if (drv->format == IMGFMT_YUY2) {
- int image_size = drv->video_width * drv->video_height;
-
- this->out[0] = malloc_aligned(16, image_size * 3/2,
- (void*)&this->buf);
- this->out[1] = this->out[0] + image_size;
- this->out[2] = this->out[1] + image_size/4;
-
- /* fill with black (yuv 16,128,128) */
- memset(this->out[0], 16, image_size);
- memset(this->out[1], 128, image_size/4);
- memset(this->out[2], 128, image_size/4);
-
- printf("dxr3: Using YUY2->YV12 conversion\n");
- }
-
- if (this->fc) {
- printf("dxr3: closing current encoding context.\n");
- fame_close(this->fc);
- this->fc = 0;
- }
- if (!this->fc)
- this->fc = fame_open();
- if (!this->fc) {
- printf("Couldn't start the FAME library\n");
- return 1;
- }
-
- if (!this->buffer)
- this->buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
- if (!this->buffer) {
- printf("Couldn't allocate temp buffer for mpeg data\n");
- return 1;
- }
-
- this->fp = dummy_init_fp;
- this->fp.quality=drv->config->register_range(drv->config,"dxr3.fame_quality",90, 10,100, "Dxr3enc: fame mpeg encoding quality",NULL,NULL,NULL);
- /* the really interesting bit is the quantizer scale. The formula
- * below is copied from libfame's sources (could be changed in the
- * future) */
- printf("dxr3: quality %d -> quant scale = %d\n", this->fp.quality,
- 1 + (30*(100-this->fp.quality)+50)/100);
- this->fp.width = drv->video_width;
- this->fp.height = drv->video_height;
- this->fp.profile = "mpeg1";
- this->fp.coding = "I";
- this->fp.verbose = 1; /* we don't need any more info.. thanks :) */
-
- /* start guessing the framerate */
- fps = drv->fps;
- if (fabs(fps - 25) < 0.01) { /* PAL */
- printf("dxr3: setting mpeg output framerate to PAL (25 Hz)\n");
- this->fp.frame_rate_num = 25; this->fp.frame_rate_den = 1;
- }
- else if (fabs(fps - 24) < 0.01) { /* FILM */
- printf("dxr3: setting mpeg output framerate to FILM (24 Hz))\n");
- this->fp.frame_rate_num = 24; this->fp.frame_rate_den = 1;
- }
- else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
- printf("dxr3: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
- this->fp.frame_rate_num = 24000; this->fp.frame_rate_den = 1001;
- }
- else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
- printf("dxr3: setting mpeg output framerate to NTSC (29.97 Hz)\n");
- this->fp.frame_rate_num = 30000; this->fp.frame_rate_den = 1001;
- }
- else { /* try 1/fps, if not legal, libfame will go to PAL */
- this->fp.frame_rate_num = (int)(fps + 0.5); this->fp.frame_rate_den = 1;
- printf("dxr3: trying to set mpeg output framerate to %d Hz\n",
- this->fp.frame_rate_num);
- }
- fame_init (this->fc, &this->fp, this->buffer, DEFAULT_BUFFER_SIZE);
-
- return 0;
+ fame_data_t *this = (fame_data_t*)drv->enc;
+ double fps;
+
+ /* if YUY2 and dimensions changed, we need to re-allocate the
+ * internal YV12 buffer */
+ if (this->buf) free(this->buf);
+ this->buf = 0;
+ this->out[0] = this->out[1] = this->out[2] = 0;
+ if (drv->format == IMGFMT_YUY2) {
+ int image_size = drv->video_width * drv->video_height;
+
+ this->out[0] = malloc_aligned(16, image_size * 3/2,
+ (void*)&this->buf);
+ this->out[1] = this->out[0] + image_size;
+ this->out[2] = this->out[1] + image_size/4;
+
+ /* fill with black (yuv 16,128,128) */
+ memset(this->out[0], 16, image_size);
+ memset(this->out[1], 128, image_size/4);
+ memset(this->out[2], 128, image_size/4);
+
+ printf("dxr3: Using YUY2->YV12 conversion\n");
+ }
+
+ if (this->fc) {
+ printf("dxr3: closing current encoding context.\n");
+ fame_close(this->fc);
+ this->fc = 0;
+ }
+ if (!this->fc)
+ this->fc = fame_open();
+ if (!this->fc) {
+ printf("Couldn't start the FAME library\n");
+ return 1;
+ }
+
+ if (!this->buffer)
+ this->buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
+ if (!this->buffer) {
+ printf("Couldn't allocate temp buffer for mpeg data\n");
+ return 1;
+ }
+
+ this->fp = dummy_init_fp;
+ this->fp.quality=drv->config->register_range(drv->config,"dxr3.fame_quality",90, 10,100, "Dxr3enc: fame mpeg encoding quality",NULL,NULL,NULL);
+ /* the really interesting bit is the quantizer scale. The formula
+ * below is copied from libfame's sources (could be changed in the
+ * future) */
+ printf("dxr3: quality %d -> quant scale = %d\n", this->fp.quality,
+ 1 + (30*(100-this->fp.quality)+50)/100);
+ this->fp.width = drv->video_width;
+ this->fp.height = drv->video_height;
+ this->fp.profile = "mpeg1";
+ this->fp.coding = "I";
+ this->fp.verbose = 1; /* we don't need any more info.. thanks :) */
+
+ /* start guessing the framerate */
+ fps = drv->fps;
+ if (fabs(fps - 25) < 0.01) { /* PAL */
+ printf("dxr3: setting mpeg output framerate to PAL (25 Hz)\n");
+ this->fp.frame_rate_num = 25; this->fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 24) < 0.01) { /* FILM */
+ printf("dxr3: setting mpeg output framerate to FILM (24 Hz))\n");
+ this->fp.frame_rate_num = 24; this->fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */
+ printf("dxr3: setting mpeg output framerate to NTSC-FILM (23.976 Hz))\n");
+ this->fp.frame_rate_num = 24000; this->fp.frame_rate_den = 1001;
+ }
+ else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
+ printf("dxr3: setting mpeg output framerate to NTSC (29.97 Hz)\n");
+ this->fp.frame_rate_num = 30000; this->fp.frame_rate_den = 1001;
+ }
+ else { /* try 1/fps, if not legal, libfame will go to PAL */
+ this->fp.frame_rate_num = (int)(fps + 0.5); this->fp.frame_rate_den = 1;
+ printf("dxr3: trying to set mpeg output framerate to %d Hz\n",
+ this->fp.frame_rate_num);
+ }
+ fame_init (this->fc, &this->fp, this->buffer, DEFAULT_BUFFER_SIZE);
+
+ return 0;
}
static int fame_prepare_frame(fame_data_t* this, dxr3_driver_t *drv,
- dxr3_frame_t *frame)
+ dxr3_frame_t *frame)
{
- int i, j, w2;
- uint8_t *y, *u, *v, *yuy2;
-
- if (frame->vo_frame.bad_frame)
- return 0;
-
- if (frame->vo_frame.format == IMGFMT_YUY2) {
- /* need YUY2->YV12 conversion */
- if (! (this->out[0] && this->out[1] && this->out[2]) ) {
- printf("dxr3: Internal error. Internal YV12 buffer not created.\n");
- return 1;
- }
- /* need conversion */
- y = this->out[0] + frame->width*drv->top_bar;
- u = this->out[1] + frame->width/2*(drv->top_bar/2);
- v = this->out[2] + frame->width/2*(drv->top_bar/2);
- yuy2 = frame->vo_frame.base[0];
- w2 = frame->width/2;
- for (i=0; i<frame->height; i+=2) {
- for (j=0; j<w2; j++) {
- /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
- *(y++) = *(yuy2++);
- *(u++) = *(yuy2++);
- *(y++) = *(yuy2++);
- *(v++) = *(yuy2++);
- }
- /* down sampling */
- for (j=0; j<w2; j++) {
- /* skip every second line for U and V */
- *(y++) = *(yuy2++);
- yuy2++;
- *(y++) = *(yuy2++);
- yuy2++;
- }
- }
- /* reset for encoder */
- y = this->out[0];
- u = this->out[1];
- v = this->out[2];
- }
- else { /* YV12 */
- y = frame->real_base[0];
- u = frame->real_base[1];
- v = frame->real_base[2];
- }
-
- this->yuv.y=y;
- this->yuv.u=u;
- this->yuv.v=v;
- return 0;
+ int i, j, w2;
+ uint8_t *y, *u, *v, *yuy2;
+
+ if (frame->vo_frame.bad_frame)
+ return 0;
+
+ if (frame->vo_frame.format == IMGFMT_YUY2) {
+ /* need YUY2->YV12 conversion */
+ if (! (this->out[0] && this->out[1] && this->out[2]) ) {
+ printf("dxr3: Internal error. Internal YV12 buffer not created.\n");
+ return 1;
+ }
+ /* need conversion */
+ y = this->out[0] + frame->width*drv->top_bar;
+ u = this->out[1] + frame->width/2*(drv->top_bar/2);
+ v = this->out[2] + frame->width/2*(drv->top_bar/2);
+ yuy2 = frame->vo_frame.base[0];
+ w2 = frame->width/2;
+ for (i=0; i<frame->height; i+=2) {
+ for (j=0; j<w2; j++) {
+ /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
+ *(y++) = *(yuy2++);
+ *(u++) = *(yuy2++);
+ *(y++) = *(yuy2++);
+ *(v++) = *(yuy2++);
+ }
+ /* down sampling */
+ for (j=0; j<w2; j++) {
+ /* skip every second line for U and V */
+ *(y++) = *(yuy2++);
+ yuy2++;
+ *(y++) = *(yuy2++);
+ yuy2++;
+ }
+ }
+ /* reset for encoder */
+ y = this->out[0];
+ u = this->out[1];
+ v = this->out[2];
+ }
+ else { /* YV12 */
+ y = frame->real_base[0];
+ u = frame->real_base[1];
+ v = frame->real_base[2];
+ }
+
+ this->yuv.y=y;
+ this->yuv.u=u;
+ this->yuv.v=v;
+ return 0;
}
static int fame_on_display_frame( dxr3_driver_t* drv, dxr3_frame_t* frame)
{
- char tmpstr[128];
- em8300_register_t regs;
- int size;
- fame_data_t *this = (fame_data_t*)drv->enc;
-
- if ((frame->width != this->fp.width) || (frame->oheight != this->fp.height)) {
- /* probably an old frame for a previous context. ignore it */
- return 0;
- }
-
- fame_prepare_frame(this, drv, frame);
- size = fame_encode_frame(this->fc, &this->yuv, NULL);
-
- if (drv->enhanced_mode)
- {
- regs.microcode_register=1; /* Yes, this is a MC Reg */
- regs.reg = MV_COMMAND;
- regs.val=6; /* Mike's mystery number :-) */
- ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, &regs);
- }
-
- if (drv->fd_video == CLOSED_FOR_ENCODER) {
- snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", drv->devname, drv->devnum);
- drv->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK);
- }
- if (drv->fd_video >= 0)
- /* FIXME: Is a SETPTS necessary here? */
- if (write(drv->fd_video, this->buffer, size) < 0)
- perror("dxr3: writing to video device");
- frame->vo_frame.displayed(&frame->vo_frame);
- return 0;
+ char tmpstr[128];
+ em8300_register_t regs;
+ int size;
+ fame_data_t *this = (fame_data_t*)drv->enc;
+
+ if ((frame->width != this->fp.width) || (frame->oheight != this->fp.height)) {
+ /* probably an old frame for a previous context. ignore it */
+ return 0;
+ }
+
+ fame_prepare_frame(this, drv, frame);
+ size = fame_encode_frame(this->fc, &this->yuv, NULL);
+
+ if (drv->enhanced_mode)
+ {
+ regs.microcode_register=1; /* Yes, this is a MC Reg */
+ regs.reg = MV_COMMAND;
+ regs.val=6; /* Mike's mystery number :-) */
+ ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, &regs);
+ }
+
+ if (drv->fd_video == CLOSED_FOR_ENCODER) {
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", drv->devname, drv->devnum);
+ drv->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK);
+ }
+ if (drv->fd_video >= 0)
+ /* FIXME: Is a SETPTS necessary here? */
+ if (write(drv->fd_video, this->buffer, size) < 0)
+ perror("dxr3: writing to video device");
+ frame->vo_frame.displayed(&frame->vo_frame);
+ return 0;
}
static int fame_on_close( dxr3_driver_t *drv )
{
- fame_data_t *this = (fame_data_t*)drv->enc;
- if (this->fc) {
- fame_close(this->fc);
- }
- free(this);
- drv->enc = 0;
- return 0;
+ fame_data_t *this = (fame_data_t*)drv->enc;
+ if (this->fc) {
+ fame_close(this->fc);
+ }
+ free(this);
+ drv->enc = 0;
+ return 0;
}
int dxr3_fame_init( dxr3_driver_t *drv )
{
- fame_data_t* this;
- this = malloc(sizeof(fame_data_t));
- if (! this)
- return 1;
- memset(this, 0, sizeof(fame_data_t));
- this->encoder_data.type = ENC_FAME;
- /* fame context */
- this->fc = 0;
- this->encoder_data.on_update_format = fame_on_update_format;
- this->encoder_data.on_frame_copy = NULL;
- this->encoder_data.on_display_frame = fame_on_display_frame;
- this->encoder_data.on_close = fame_on_close;
- drv->enc = (encoder_data_t*)this;
- return 0;
+ fame_data_t* this;
+ this = malloc(sizeof(fame_data_t));
+ if (! this)
+ return 1;
+ memset(this, 0, sizeof(fame_data_t));
+ this->encoder_data.type = ENC_FAME;
+ /* fame context */
+ this->fc = 0;
+ this->encoder_data.on_update_format = fame_on_update_format;
+ this->encoder_data.on_frame_copy = NULL;
+ this->encoder_data.on_display_frame = fame_on_display_frame;
+ this->encoder_data.on_close = fame_on_close;
+ drv->enc = (encoder_data_t*)this;
+ return 0;
}
#endif
diff --git a/src/dxr3/nav_read.c b/src/dxr3/nav_read.c
index 0a8ac3813..7b139ffd6 100644
--- a/src/dxr3/nav_read.c
+++ b/src/dxr3/nav_read.c
@@ -1,207 +1 @@
-/**
- * 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);
-}
-
+#include "../libspudec/nav_read.c"
diff --git a/src/dxr3/nav_read.h b/src/dxr3/nav_read.h
index ba4dc4dca..daa7de215 100644
--- a/src/dxr3/nav_read.h
+++ b/src/dxr3/nav_read.h
@@ -1,41 +1 @@
-/**
- * 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 */
+#include "../libspudec/nav_read.h"
diff --git a/src/dxr3/nav_types.h b/src/dxr3/nav_types.h
index 032bdedf7..cb760da9d 100644
--- a/src/dxr3/nav_types.h
+++ b/src/dxr3/nav_types.h
@@ -1,404 +1 @@
-/**
- * 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 */
+#include "../libspudec/nav_types.h"