diff options
-rw-r--r-- | src/dxr3/Makefile.am | 4 | ||||
-rw-r--r-- | src/dxr3/bswap.h | 88 | ||||
-rw-r--r-- | src/dxr3/dxr3.h | 32 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_spu.c | 711 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_video.c | 1245 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.c | 247 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.h | 37 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.c | 460 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.h | 162 | ||||
-rw-r--r-- | src/dxr3/dxr3_vo_core.c | 1166 | ||||
-rw-r--r-- | src/dxr3/mpeg_encoders.c | 670 | ||||
-rw-r--r-- | src/dxr3/nav_read.c | 208 | ||||
-rw-r--r-- | src/dxr3/nav_read.h | 42 | ||||
-rw-r--r-- | src/dxr3/nav_types.h | 405 |
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, ®s)); -} - -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, ®s); } -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, ¤t_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, ®s); +} + +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, ®s); @@ -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, ®s); - } - - 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, ®s); + } + + 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" |