summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Lampard <mlampard@users.sourceforge.net>2001-11-07 12:30:54 +0000
committerMike Lampard <mlampard@users.sourceforge.net>2001-11-07 12:30:54 +0000
commit40e61e9f8ce31f5802856e303e521a4741500327 (patch)
tree8ad94f9b753c0b07bb8fbba462e8848e098cf0db /src
parent887aef7c6f3f6f728d2324815b9b05060be8405a (diff)
downloadxine-lib-40e61e9f8ce31f5802856e303e521a4741500327.tar.gz
xine-lib-40e61e9f8ce31f5802856e303e521a4741500327.tar.bz2
breakup of dxr3 videoout plugin to allow for easier syncronisation of
encoding and standard plugins CVS patchset: 979 CVS date: 2001/11/07 12:30:54
Diffstat (limited to 'src')
-rw-r--r--src/dxr3/Makefile.am8
-rw-r--r--src/dxr3/dxr3_decoder.c6
-rw-r--r--src/dxr3/dxr3_video_out.h132
-rw-r--r--src/dxr3/dxr3_vo_core.c623
-rw-r--r--src/dxr3/dxr3_vo_encoder.c622
-rw-r--r--src/dxr3/dxr3_vo_encoder.h52
-rw-r--r--src/dxr3/dxr3_vo_standard.c219
7 files changed, 1656 insertions, 6 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am
index ff838b586..8c09a7762 100644
--- a/src/dxr3/Makefile.am
+++ b/src/dxr3/Makefile.am
@@ -1,6 +1,6 @@
CFLAGS = @GLOBAL_CFLAGS@ @X_CFLAGS@ $(LINUX_INCLUDE)
-EXTRA_DIST = dxr3_decoder.c video_out_dxr3.c video_out_dxr3enc.c overlay.c
+EXTRA_DIST = dxr3_decoder.c dxr3_vo_core.c dxr3_vo_encoder.c dxr3_vo_standard.c
LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
@@ -18,14 +18,14 @@ lib_LTLIBRARIES = $(dxr3_modules) $(dxr3enc_module)
xineplug_decode_dxr3_la_SOURCES = dxr3_decoder.c
xineplug_decode_dxr3_la_LDFLAGS = -avoid-version -module
-xineplug_vo_out_dxr3_la_SOURCES = video_out_dxr3.c overlay.c
+xineplug_vo_out_dxr3_la_SOURCES = dxr3_vo_standard.c dxr3_vo_core.c
xineplug_vo_out_dxr3_la_LDFLAGS = -avoid-version -module $(X_LIBS)
-xineplug_vo_out_dxr3enc_la_SOURCES = video_out_dxr3enc.c overlay.c
+xineplug_vo_out_dxr3enc_la_SOURCES = dxr3_vo_encoder.c dxr3_vo_core.c
xineplug_vo_out_dxr3enc_la_LDFLAGS = \
-avoid-version -module -lfame $(X_LIBS)
-include_HEADERS = dxr3_overlay.h
+include_HEADERS = dxr3_video_out.h dxr3_vo_encoder.h
debug:
@$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(LINUX_INCLUDE)"
diff --git a/src/dxr3/dxr3_decoder.c b/src/dxr3/dxr3_decoder.c
index a84358a9f..bf7ec0e81 100644
--- a/src/dxr3/dxr3_decoder.c
+++ b/src/dxr3/dxr3_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: dxr3_decoder.c,v 1.28 2001/11/02 13:18:27 mlampard Exp $
+ * $Id: dxr3_decoder.c,v 1.29 2001/11/07 12:30:54 mlampard Exp $
*
* dxr3 video and spu decoder plugin. Accepts the video and spu data
* from XINE and sends it directly to the corresponding dxr3 devices.
@@ -586,7 +586,9 @@ static void spudec_event_listener (void *this_gen, xine_event_t *event_gen) {
strerror(errno));
}
break;
- /* Temporarily use the stream title to find out if we have a menu... */
+ /* 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"))
diff --git a/src/dxr3/dxr3_video_out.h b/src/dxr3/dxr3_video_out.h
new file mode 100644
index 000000000..726a8ea5a
--- /dev/null
+++ b/src/dxr3/dxr3_video_out.h
@@ -0,0 +1,132 @@
+/*
+ * Globals for dxr3 videoout plugins
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+
+#include <linux/em8300.h>
+#include "video_out.h"
+#include "xine_internal.h"
+
+/* for fast_memcpy: */
+#include "memcpy.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#include "../video_out/video_out_x11.h"
+
+#define LOOKUP_DEV "dxr3_devname"
+#define DEFAULT_DEV "/dev/em8300"
+
+struct coeff {
+ float k,m;
+};
+
+typedef struct {
+ int fd_control;
+ int overlay_enabled;
+ 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 struct dxr3_driver_s {
+ vo_driver_t vo_driver;
+ config_values_t *config;
+ int fd_control;
+ int fd_video;
+ int aspectratio;
+ int tv_mode;
+ em8300_bcs_t bcs;
+
+ /* for encoder plugin */
+ uint8_t *out[3]; /* aligned buffer for YV12 data, copied from frames */
+ uint8_t *buf[3]; /* unaligned YV12 buffer */
+ int oheight; /* height after adding black bars to correct a.r. */
+ int video_iheight; /* input height (before adding black bars) */
+ int video_height; /* output height (after adding bars) */
+
+ /* for overlay */
+ dxr3_overlay_t overlay;
+ Display *display;
+ Drawable win;
+ GC gc;
+ XColor color;
+ int xpos, ypos;
+ int width, height;
+ int overlay_enabled;
+ float desired_ratio;
+
+ int zoom_enabled;
+
+ int video_width;
+ int video_aspect;
+
+ char *user_data;
+
+ void (*request_dest_size) (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;
+ uint8_t *mem[3]; /* allocated for YV12 or YUY2 buffers */
+ uint8_t *real_base[3]; /* same buffers alligned on 16 bytes */
+ int format;
+ dxr3_driver_t *vo_instance; /* points to self, for use in dxr3_frame_copy */
+ int copy_calls; /* counts calls to dxr3_frame_copy function */
+#if USE_MPEG_BUFFER
+ unsigned char *mpeg; /* encoded mpeg data */
+ unsigned int mpeg_size; /* length of data */
+#endif
+}dxr3_frame_t;
+
+static char *devname;
+
+/* func definitions */
+/* Overlay functions */
+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);
+
+void dxr3_overlay_buggy_preinit(dxr3_overlay_t *this, int fd);
+int dxr3_overlay_read_state(dxr3_overlay_t *this);
+void dxr3_get_keycolor(dxr3_driver_t *this);
+void dxr3_read_config(dxr3_driver_t *this);
+
+void *malloc_aligned (size_t alignment, size_t size, void **mem);
+void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis);
+
+/* xine accessable functions */
+int dxr3_get_property (vo_driver_t *this_gen, int property);
+int dxr3_set_property (vo_driver_t *this_gen, int property, int value);
+void dxr3_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max);
+int dxr3_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data);
+
+
diff --git a/src/dxr3/dxr3_vo_core.c b/src/dxr3/dxr3_vo_core.c
new file mode 100644
index 000000000..7004d949e
--- /dev/null
+++ b/src/dxr3/dxr3_vo_core.c
@@ -0,0 +1,623 @@
+/*************************************************************************
+ * 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 *
+ *************************************************************************/
+
+#include "dxr3_video_out.h"
+
+void *malloc_aligned (size_t alignment, size_t size, void **mem) {
+ char *aligned;
+
+ aligned = malloc (size+alignment);
+ *mem = aligned;
+
+ while ((int) aligned % alignment)
+ aligned++;
+
+ return aligned;
+}
+
+
+/****** 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)
+{
+ XWindowAttributes a;
+ Window junkwin;
+ int rx, ry;
+
+ 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);
+
+ 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);
+}
+
+
+/****** 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;
+
+ 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 *
+ ***************************************************************/
+void dxr3_read_config(dxr3_driver_t *this)
+{
+ char* str;
+ config_values_t *config=this->config;
+
+ if (ioctl(this->fd_control, EM8300_IOCTL_GETBCS, &this->bcs))
+ fprintf(stderr, "dxr3_vo: cannot read bcs values (%s)\n",
+ strerror(errno));
+
+ this->bcs.contrast = config->lookup_int(config, "dxr3_contrast", this->bcs.contrast);
+ this->bcs.saturation = config->lookup_int(config, "dxr3_saturation", this->bcs.saturation);
+ this->bcs.brightness = config->lookup_int(config, "dxr3_brightness", this->bcs.brightness);
+
+ this->vo_driver.set_property(&this->vo_driver,
+ VO_PROP_ASPECT_RATIO, ASPECT_FULL);
+
+ str = config->lookup_str(config, "dxr3_tvmode", "default");
+ if (!strcmp(str, "ntsc")) {
+ this->tv_mode = EM8300_VIDEOMODE_NTSC;
+ fprintf(stderr, "dxr3_vo: setting tv_mode to NTSC\n");
+ } else if (!strcmp(str, "pal")) {
+ this->tv_mode = EM8300_VIDEOMODE_PAL;
+ fprintf(stderr, "dxr3_vo: setting tv_mode to PAL 50Hz\n");
+ } else if (!strcmp(str, "pal60")) {
+ this->tv_mode = EM8300_VIDEOMODE_PAL60;
+ fprintf(stderr, "dxr3_vo: setting tv_mode to PAL 60Hz\n");
+ } else if (!strcmp(str, "overlay")) {
+ this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
+ fprintf(stderr, "dxr3_vo: setting up overlay mode\n");
+ if (dxr3_overlay_read_state(&this->overlay) == 0) {
+ this->overlay_enabled = 1;
+
+ str = config->lookup_str(config, "dxr3_keycolor", "0x80a040");
+ sscanf(str, "%x", &this->overlay.colorkey);
+
+ str = config->lookup_str(config, "dxr3_color_interval", "50.0");
+ sscanf(str, "%f", &this->overlay.color_interval);
+ } else {
+ fprintf(stderr, "dxr3_vo: please run autocal, overlay disabled\n");
+ }
+ } else {
+ this->tv_mode = EM8300_VIDEOMODE_DEFAULT;
+ }
+ if(!this->overlay_enabled)
+ this->zoom_enabled=config->lookup_int(config, "dxr3_zoom16_9", 0);
+
+ if (this->tv_mode != EM8300_VIDEOMODE_DEFAULT)
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode))
+ fprintf(stderr, "dxr3_vo: setting video mode failed.");
+}
+
+
+/******** is this window fullscreen? ************/
+static 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;
+}
+
+
+/******* Experimental zoom function for tvout only *********
+ * (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);
+
+}
+
+int dxr3_get_property (vo_driver_t *this_gen, int property)
+{
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ int val;
+
+ 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;
+ default:
+ val = 0;
+ fprintf(stderr, "dxr3_vo: property %d not implemented!\n", property);
+ }
+
+ return val;
+}
+
+int dxr3_set_property (vo_driver_t *this_gen,
+ 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 = is_fullscreen(this);
+
+ if (value == ASPECT_ANAMORPHIC) {
+ fprintf(stderr, "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 {
+ fprintf(stderr, "dxr3_vo: setting aspect ratio to full\n");
+ val = EM8300_ASPECTRATIO_4_3;
+ this->desired_ratio = 4.0/3.0;
+ }
+
+ if(val==EM8300_ASPECTRATIO_16_9 && this->zoom_enabled && !this->overlay_enabled){
+ fprintf(stderr, "dxr3_vo: enabling 16:9 zoom\n");
+ val=EM8300_ASPECTRATIO_4_3;
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
+ fprintf(stderr, "dxr3_vo: failed to set aspect ratio (%s)\n",
+ strerror(errno));
+ dxr3_zoomTV(this);
+ }else
+ if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val))
+ fprintf(stderr, "dxr3_vo: failed to set aspect ratio (%s)\n",
+ strerror(errno));
+
+ if (this->overlay_enabled && !fullscreen){
+ int foo;
+ this->request_dest_size(this->user_data, this->width,
+ this->width/this->desired_ratio, &foo, &foo, &foo, &foo);
+ }
+ break;
+ case VO_PROP_COLORKEY:
+ fprintf(stderr, "dxr3_vo: VO_PROP_COLORKEY not implemented!");
+ this->overlay.colorkey = val;
+ break;
+ }
+
+ if (bcs_changed){
+ if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs))
+ fprintf(stderr, "dxr3_vo: bcs set failed (%s)\n",
+ strerror(errno));
+ this->config->set_int(this->config, "dxr3_contrast", this->bcs.contrast);
+ this->config->set_int(this->config, "dxr3_saturation", this->bcs.saturation);
+ this->config->set_int(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)
+{
+ /* 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)
+{
+ 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)
+{
+ dxr3_driver_t *this = (dxr3_driver_t*) this_gen;
+ x11_rectangle_t *area;
+ XWindowAttributes a;
+
+ if (!this->overlay_enabled) return 0;
+
+ switch (data_type) {
+ case GUI_DATA_EX_DEST_POS_SIZE_CHANGED:
+ area = (x11_rectangle_t*) data;
+ dxr3_overlay_adapt_area(this, area->x, area->y, area->w, area->h);
+ 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);
+ break;
+ case GUI_DATA_EX_DRAWABLE_CHANGED:
+ 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;
+ 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;
+#ifdef HAVE_XINERAMA
+ 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);
+
+ /* 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
+#endif
+ {
+ 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->request_dest_size = (void *)vis->request_dest_size;
+ 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 *
+ **************************************************************************/
+
+#define TYPE_INT 1
+#define TYPE_XINT 2
+#define TYPE_COEFF 3
+#define TYPE_FLOAT 4
+
+struct lut_entry {
+ char *name;
+ int type;
+ void *ptr;
+};
+
+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;
+}
+
+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;
+ return 1;
+ }
+ 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;
+
+ 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(!(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," ");
+ switch(type) {
+ case TYPE_INT:
+ sscanf(tok,"%d",(int *)ptr);
+ break;
+ case TYPE_XINT:
+ sscanf(tok,"%x",(int *)ptr);
+ break;
+ case TYPE_FLOAT:
+ sscanf(tok,"%f",(float *)ptr);
+ break;
+ case TYPE_COEFF:
+ for(j=0;j<3;j++) {
+ sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
+ tok=strtok(NULL," ");
+ sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
+ tok=strtok(NULL," ");
+ }
+ break;
+ }
+ }
+ }
+ free(lut);
+ fclose(fp);
+ 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 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;
+
+ overlay_limit = /* lower 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) 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_UPPER;
+ attr.value = overlay_limit;
+ return ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr);
+}
+
+
+int dxr3_overlay_set_mode(dxr3_overlay_t *this, int 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);
+}
+
+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);
+}
+
+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);
+}
+
+int dxr3_overlay_set_signalmode(dxr3_overlay_t *this,int 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);
+}
diff --git a/src/dxr3/dxr3_vo_encoder.c b/src/dxr3/dxr3_vo_encoder.c
new file mode 100644
index 000000000..cd226d91a
--- /dev/null
+++ b/src/dxr3/dxr3_vo_encoder.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix 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_vo_encoder.c,v 1.1 2001/11/07 12:30:54 mlampard Exp $
+ *
+ * mpeg1 encoding video out plugin for the dxr3.
+ *
+ * modifications to the original dxr3 video out plugin by
+ * Mike Lampard <mike at web2u.com.au>
+ * this first standalone version by
+ * Harm van der Heijden <hrm at users.sourceforge.net>
+ *
+ * Changes are mostly in dxr3_update_frame_format() (init stuff),
+ * dxr3_frame_copy() (encoding), and dxr3_display_frame() (send stream
+ * to device). The driver and frame structs are changed too.
+ *
+ * What it does
+ * - automatically insert black borders to correct a.r. to 16:9 of 4:3
+ * if needed (these are the only ones that dxr3 supports).
+ * - detect framerate from frame's duration value and set it as mpeg1's
+ * framerate. We are hampered a little by the fact that mpeg1 supports
+ * a limited number of frame rates. Most notably 23.976 (NTSC-FILM)
+ * is missing
+ * - (ab)uses the vo_frame_t->copy() function to encode mpeg1 as soon as
+ * the frame is available.
+ * - full support for YUY2 output; automatic conversion to YV12
+ *
+ * TODO:
+ * - try ffmpeg encoder instead of libfame
+ * - jerkiness issues with mpeg1 output (possibly fixed, see below)
+ * - sync issues (possibly fixed, see below)
+ * - split off code that is shared with original dxr3 decoder, for
+ * maintainability of the whole thing.
+ * - init; sometimes (usually first time after boot) there's no output
+ * to tv. The second attempt usually works.
+ * - test with overlay (haven't figured out yet how to get it working
+ * on my system, not even with standard dxr3 driver -- harm)
+ *
+ ***** Update 28/10/2001 by Harm
+ *
+ * I've implemented a method for buffering the mpeg data
+ * (basically copying it to the frame) for display (read: write to mpeg
+ * device) when xine requests it via dxr3_frame_display. It helps sync,
+ * but playback is still not smooth.
+ *
+ * buffering enabled by default, see USE_MPEG_BUFFER define.
+ *
+ * Moved the mpeg device (/dev/em8300_fd) file descriptor to vo_driver_t;
+ * very weird: to be able to use it in frame_display, I must reopen it
+ * there! Is that a thread thing or something? Normally you'd open it in
+ * the driver's init function.
+ *
+ ***** Update 29/10/2001 by Harm
+ *
+ * Mike Lampard figured out a solution to the jerky playback problem that
+ * seems to work well; write the value 6 to the MV_COMMAND register!
+ * I'm guessing this puts the dxr3 playback in some sort of scan mode
+ * where it plays frames as soon as it can. This combines well with our
+ * method because we deliver them when they need displaying.
+ *
+ * This fix is turned on/off by setting USE_MAGIC_REGISTER to 1/0.
+ *
+ * Note, we write to the register at every frame; possibly overkill, but
+ * there seems to be no noticeable overhead and better safe than sorry...
+ *
+ * If you still get occasional jerky playback, try lowering the
+ * mpeg1 encoding qualtiy (.xinerc var dxr3enc_quality) first. On my
+ * system, there are occasional scenes with high entropy that libfame
+ * can't encode at hi quality and 25 fps. Remember, the time it takes
+ * to encode a frame is not fixed but depends on the complexity!
+ *
+ * You wanna hear a funny thing? With the register fix in place, it no
+ * longer seems to matter whether USE_MPEG_BUFFER is on or off; in both
+ * cases A/V sync seems fine! Weird... I'm leaving it on for the moment,
+ * to be safe. It should give the encoder the option to spend more than
+ * 1/fps on occasional frames.
+ *
+ * Other changes:
+ * - .xinerc: renamed dxr3_enc_quality to dxr3enc_quality
+ * - .xinerc: added dxr3_file for output of mpeg stream to file, for
+ * debugging. set to <none> or delete the entry to send stream to dxr3.
+ *
+ ***** Update 29/10/2001 (later) by Harm
+ *
+ * Added support for encoding using libavcodec from ffmpeg. See the defines
+ * USE_LIBFAME and USE_FFMPEG (mutually exclusive)
+ * These defines are getting quite messy; there's three of them now.
+ * Need to make some decisions soon :-)
+ *
+ * If using ffmpeg, do not link against libavcodec from xine sources!
+ * There's something wrong with that one, you'll get rubbish output.
+ * Get the ffmpeg cvs, compile, then copy libavcodec.a to /usr/local/lib
+ * or something.
+ *
+ * At the moment libffmpeg's encoder output is pretty crappy, with weird
+ * ghost effects left and right of objects. At the moment using a fixed
+ * quantizer value. Somewhat more cpu intensive than libfame.
+ */
+
+/* encoder specific config/setup stuff *
+ * must be before dxr3_video_out.h */
+#include "dxr3_vo_encoder.h"
+
+/* dxr3 vo globals */
+#include "dxr3_video_out.h"
+
+
+static uint32_t dxr3_get_capabilities (vo_driver_t *this_gen)
+{
+ /* Since we have no vo format, we return dummy values here */
+ return VO_CAP_YV12 | VO_CAP_YUY2 |
+ VO_CAP_SATURATION | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST;
+}
+
+/* This are dummy functions to fill in the frame object */
+
+static void dummy_frame_field (vo_frame_t *vo_img, int which_field)
+{
+ fprintf(stderr, "dxr3_vo: dummy_frame_field called!\n");
+}
+
+static void dxr3_frame_dispose (vo_frame_t *frame_gen)
+{
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ if (frame->mem[0])
+ free (frame->mem[0]);
+ if (frame->mem[1])
+ free (frame->mem[1]);
+ if (frame->mem[2])
+ free (frame->mem[2]);
+#if USE_MPEG_BUFFER
+ free(frame->mpeg);
+#endif
+ free(frame);
+}
+
+static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src);
+
+static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen)
+{
+ /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
+ dxr3_frame_t *frame;
+
+ frame = (dxr3_frame_t *) malloc (sizeof (dxr3_frame_t));
+ memset (frame, 0, sizeof(dxr3_frame_t));
+
+ frame->vo_frame.copy = dxr3_frame_copy;
+ frame->vo_frame.field = dummy_frame_field;
+ frame->vo_frame.dispose = dxr3_frame_dispose;
+
+#if USE_MPEG_BUFFER
+ frame->mpeg = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
+#endif
+
+ return (vo_frame_t*) frame;
+}
+
+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)
+{
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ int aspect;
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ int image_size, oheight;
+ float fps;
+
+ /* reset the copy calls counter (number of calls to dxr3_frame_copy) */
+ frame->copy_calls = 0;
+ frame->vo_instance = this;
+
+ aspect = this->aspectratio;
+ oheight = this->oheight;
+
+ /* check aspect ratio, see if we need to add black borders */
+ if ((this->video_width != width) || (this->video_iheight != height) ||
+ (this->video_aspect != ratio_code)) {
+ switch (ratio_code) {
+ case XINE_ASPECT_RATIO_4_3: /* 4:3 */
+ aspect = ASPECT_FULL;
+ oheight = height;
+ break;
+ case XINE_ASPECT_RATIO_ANAMORPHIC:
+ aspect = ASPECT_ANAMORPHIC;
+ oheight = height;
+ break;
+ default: /* assume square pixel */
+ aspect = ASPECT_ANAMORPHIC;
+ oheight = (int)(width * 9./16.);
+ if (oheight < height) { /* frame too high, try 4:3 */
+ aspect = ASPECT_FULL;
+ oheight = (int)(width * 3./4.);
+ }
+ }
+ /* find closest multiple of 16 */
+ oheight = 16*(int)(oheight / 16. + 0.5);
+ if (oheight < height)
+ oheight = height;/* no good, need horizontal bars (not yet) */
+
+ this->oheight = oheight;
+
+ /* Tell the viewers about the aspect ratio stuff. */
+ if (oheight - height > 0)
+ printf("dxr3enc: adding %d black lines to get %s a.r.\n",
+ oheight-height, aspect == ASPECT_FULL ? "4:3" : "16:9");
+
+ /* if YUY2 and dimensions changed, we need to re-allocate the
+ * internal YV12 buffer */
+ if (format == IMGFMT_YUY2) {
+ if (this->buf[0]) free(this->buf[0]);
+ if (this->buf[1]) free(this->buf[1]);
+ if (this->buf[2]) free(this->buf[2]);
+
+ image_size = width * oheight;
+
+ this->out[0] = malloc_aligned(16, image_size, (void*)&this->buf[0]);
+ this->out[1] = malloc_aligned(16, image_size/4, (void*)&this->buf[1]);
+ this->out[2] = malloc_aligned(16, image_size/4, (void*)&this->buf[2]);
+
+ /* 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("dxr3enc: Using YUY2->YV12 conversion\n");
+ }
+ }
+
+ /* if dimensions changed, we need to re-allocate frame memory */
+ if ((frame->width != width) || (frame->height != height)) {
+ if (frame->mem[0]) {
+ free (frame->mem[0]);
+ frame->mem[0] = NULL;
+ }
+ if (frame->mem[1]) {
+ free (frame->mem[1]);
+ frame->mem[1] = NULL;
+ }
+ if (frame->mem[2]) {
+ free (frame->mem[2]);
+ frame->mem[2] = NULL;
+ }
+
+ if (format == IMGFMT_YUY2) {
+ image_size = width * height; /* does not include black bars */
+ /* planar format, only base[0] */
+ frame->vo_frame.base[0] = malloc_aligned(16, image_size*2, (void**)&frame->mem[0]);
+ frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0;
+ frame->real_base[0] = frame->real_base[1] = frame->real_base[2] = 0;
+ /* we do the black bar stuff while converting to YV12 */
+ }
+ else { /* IMGFMT_YV12 */
+ image_size = width * oheight; /* includes black bars */
+ frame->real_base[0] = malloc_aligned(16,image_size,
+ (void**) &frame->mem[0]);
+ frame->real_base[1] = malloc_aligned(16,image_size/4,
+ (void**) &frame->mem[1]);
+ frame->real_base[2] = malloc_aligned(16,image_size/4,
+ (void**) &frame->mem[2]);
+ /* fill with black (yuv 16,128,128) */
+ memset(frame->real_base[0], 16, image_size);
+ memset(frame->real_base[1], 128, image_size/4);
+ memset(frame->real_base[2], 128, image_size/4);
+
+ /* fix offsets, so the decoder does not see the top black bar */
+ frame->vo_frame.base[0] = frame->real_base[0] + width * (oheight - height)/2;
+ frame->vo_frame.base[1] = frame->real_base[1] + width/2 * (oheight - height)/4;
+ frame->vo_frame.base[2] = frame->real_base[2] + width/2 * (oheight - height)/4;
+ }
+ }
+
+ frame->width = width;
+ frame->height = height;
+ frame->format = format;
+ this->video_width = width;
+ this->video_iheight = height;
+ this->video_height = oheight;
+ this->video_aspect = ratio_code;
+
+ /* init encoder if needed */
+#if USE_LIBFAME
+ if (!fc)
+ {
+ if (!(fc = fame_open ()))
+ puts ("Couldn't start the FAME library");
+
+ buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
+ fp.quality=this->config->lookup_int(this->config,"dxr3enc_quality",90);
+ fp.width = width;
+ fp.height = oheight;
+ fp.profile = "mpeg1";
+ fp.coding = "I";
+ fp.verbose = 0; /* we don't need any more info.. thanks :) */
+
+ /* start guessing the framerate */
+ fps = 90000.0/frame->vo_frame.duration;
+ if (fabs(fps - 25) < 0.01) { /* PAL */
+ printf("dxr3enc: setting mpeg output framerate to PAL (25 Hz)\n");
+ fp.frame_rate_num = 25; fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 23.976) < 0.01) { /* NTSC film */
+ /* 23.976 not supported by mpeg 1 */
+ printf("dxr3enc: setting mpeg output framerate to 24 Hz (should be 23.976)\n");
+ fp.frame_rate_num = 24; fp.frame_rate_den = 1;
+ }
+ else if (fabs(fps - 29.97) < 0.01) { /* NTSC */
+ printf("dxr3enc: setting mpeg output framerate to NTSC (29.97 Hz)\n");
+ fp.frame_rate_num = 30000; fp.frame_rate_den = 1001;
+ }
+ else { /* try 1/fps, but libfame will probably go to PAL */
+ fp.frame_rate_num = (int)(fps + 0.5); fp.frame_rate_den = 1;
+ printf("dxr3enc: trying to set mpeg output framerate to %d Hz\n",
+ fp.frame_rate_num);
+ }
+ object = fame_get_object (fc, "profile/mpeg1");
+ fame_init (fc, &fp, buffer, DEFAULT_BUFFER_SIZE);
+
+ }
+#endif
+#if USE_FFMPEG
+ if (!avc)
+ {
+ avc = malloc(sizeof(AVCodecContext));
+ memset(avc, 0, sizeof(AVCodecContext));
+ buffer = (unsigned char *) malloc (DEFAULT_BUFFER_SIZE);
+
+ avc->bit_rate = 0; /* using fixed quantizer */
+ avc->width = width;
+ avc->height = oheight;
+ avc->gop_size = 0; /* only intra */
+ avc->pix_fmt = PIX_FMT_YUV420P;
+ avc->flags = CODEC_FLAG_QSCALE; /* fix qscale = quality */
+ avc->quality = 2; /* 1-31 highest-lowest quality */
+ /* start guessing the framerate */
+ fps = 90000.0/frame->vo_frame.duration;
+ avc->frame_rate = (int)(fps*FRAME_RATE_BASE + 0.5);
+
+ if (avcodec_open(avc, avcodec)) {
+ printf("dxr3enc: error opening avcodec. Aborting...\n");
+ exit(1); /* can't think of a cleaner way at this point */
+ }
+ }
+#endif
+
+ if(this->aspectratio!=aspect)
+ dxr3_set_property (this_gen,VO_PROP_ASPECT_RATIO, aspect);
+
+#if USE_MPEG_BUFFER
+ /* safeguard */
+ frame->mpeg_size = 0;
+#endif
+}
+
+static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src)
+{
+ int size, i, j, hoffset, w2;
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ dxr3_driver_t *this = frame->vo_instance;
+ uint8_t *y, *u, *v, *yuy2;
+
+ if (frame_gen->bad_frame)
+ return;
+
+ if (frame->copy_calls == frame->height/16) {
+ /* shouldn't happen */
+ printf("dxr3enc: Internal error. Too many calls to dxr3_frame_copy (%d)\n",
+ frame->copy_calls);
+ return;
+ }
+
+ if (frame_gen->format == IMGFMT_YV12) {
+ y = frame->real_base[0];
+ u = frame->real_base[1];
+ v = frame->real_base[2];
+ }
+ else { /* must be YUY2 */
+ if (! (this->out[0] && this->out[1] && this->out[2]) ) {
+ printf("dxr3enc: Internal error. Internal YV12 buffer not created.\n");
+ return;
+ }
+ /* need conversion */
+ hoffset = (this->oheight - frame->height)/2;
+ y = this->out[0] + frame->width*(hoffset + frame->copy_calls*16);
+ u = this->out[1] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
+ v = this->out[2] + frame->width/2*(hoffset/2 + frame->copy_calls*8);
+ yuy2 = src[0];
+ w2 = frame->width/2;
+ /* we get 16 lines each time */
+ for (i=0; i<16; 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];
+ }
+
+ frame->copy_calls++;
+
+ /* frame complete yet? */
+ if (frame->copy_calls == frame->height/16) {
+#if USE_LIBFAME
+ yuv.y=y;
+ yuv.u=u;
+ yuv.v=v;
+ size = fame_encode_frame(fc, &yuv, NULL);
+ /* not sure whether libfame does bounds checking, but if we're
+ * this close to the limit there's bound to be trouble */
+ if (size >= DEFAULT_BUFFER_SIZE) {
+ printf("dxr3enc: warning, mpeg buffer too small!\n");
+ size = DEFAULT_BUFFER_SIZE;
+ }
+# if USE_MPEG_BUFFER
+ /* copy mpeg data to frame */
+ fast_memcpy(frame->mpeg, buffer, size);
+ frame->mpeg_size = size;
+# endif
+#endif
+#if USE_FFMPEG
+ avp.data[0] = y;
+ avp.data[1] = u;
+ avp.data[2] = v;
+ avp.linesize[0] = frame->width;
+ avp.linesize[1] = avp.linesize[2] = frame->width/2;
+# if USE_MPEG_BUFFER
+ size = avcodec_encode_video(avc, frame->mpeg, DEFAULT_BUFFER_SIZE, &avp);
+ frame->mpeg_size = size;
+# else
+ size = avcodec_encode_video(avc, buffer, DEFAULT_BUFFER_SIZE, &avp);
+# endif
+#endif
+#if ! USE_MPEG_BUFFER
+ /* write to device now */
+ if (write(this->fd_video, buffer, size) < 0)
+ perror("dxr3enc: writing to video device");
+#endif
+ }
+}
+
+#define MV_COMMAND 0
+
+static void dxr3_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
+{
+ char tmpstr[256];
+ dxr3_driver_t *this = (dxr3_driver_t*)this_gen;
+ dxr3_frame_t *frame = (dxr3_frame_t*)frame_gen;
+#if USE_MAGIC_REGISTER
+ em8300_register_t regs;
+
+ regs.microcode_register=1; /* Yes, this is a MC Reg */
+ regs.reg = MV_COMMAND;
+ regs.val=6; /* Mike's mystery number :-) */
+ ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &regs);
+#endif
+#if USE_MPEG_BUFFER
+ if (this->fd_video < 0) {
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname);
+ this->fd_video = open(tmpstr, O_WRONLY);
+ }
+ if (write(this->fd_video, frame->mpeg, frame->mpeg_size) < 0)
+ perror("dxr3enc: writing to video device");
+#endif
+ frame_gen->displayed (frame_gen);
+}
+
+static void dxr3_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
+ vo_overlay_t *overlay)
+{
+ /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
+ fprintf(stderr, "dxr3_vo: dummy function dxr3_overlay_blend called!\n");
+}
+
+void dxr3_exit (vo_driver_t *this_gen)
+{
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+
+
+ if(this->overlay_enabled)
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF );
+ close(this->fd_control);
+}
+
+vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
+{
+ dxr3_driver_t *this;
+ char tmpstr[100];
+ char *file_out;
+
+ /*
+ * allocate plugin struct
+ */
+
+ 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.exit = dxr3_exit;
+ this->config=config;
+
+ /* open control device */
+ devname = config->lookup_str (config, LOOKUP_DEV, DEFAULT_DEV);
+ printf("dxr3enc: Entering video init, devname=%s.\n",devname);
+ if ((this->fd_control = open(devname, O_WRONLY)) < 0) {
+ printf("dxr3enc: Failed to open control device %s (%s)\n",
+ devname, strerror(errno));
+ return 0;
+ }
+ /* output mpeg to file instead of dxr3? */
+ file_out = config->lookup_str(config, "dxr3enc_file", "<none>");
+ if (file_out && strcmp(file_out, "<none>")) {
+ this->fd_video = open(file_out, O_WRONLY | O_CREAT);
+ if (this->fd_video < 0) {
+ perror("dxr3enc: failed to open output file");
+ return 0;
+ }
+ }
+ else {
+ /* open video device */
+ snprintf (tmpstr, sizeof(tmpstr), "%s_mv", devname);
+ if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) {
+ printf("dxr3enc: failed to open video device %s (%s)\n",
+ tmpstr, strerror(errno));
+ return 0;
+ }
+#if USE_MPEG_BUFFER
+ /* we have to close now and open the first time we get
+ * to display_frame. weird... */
+ close(this->fd_video);
+ this->fd_video = -1;
+#endif
+ }
+ gather_screen_vars(this, visual_gen);
+
+ /* default values */
+ this->overlay_enabled = 0;
+ this->aspectratio = ASPECT_FULL;
+
+ dxr3_read_config(this);
+
+ if (this->overlay_enabled) {
+ dxr3_get_keycolor(this);
+ dxr3_overlay_buggy_preinit(&this->overlay, this->fd_control);
+ }
+
+#if USE_LIBFAME
+ /* fame context */
+ fc = 0;
+#endif
+#if USE_FFMPEG
+ avc = 0;
+ avcodec_init();
+ /* this register_all() is not really needed, but it gives us a good
+ * way to sniff out bad libavcodecs */
+ avcodec_register_all();
+ avcodec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
+ if (! avcodec) {
+ /* tell tale sign of bad libavcodec */
+ printf("dxr3enc: can't find mpeg1 encoder! libavcodec is rotten!\n");
+ return 0;
+ }
+#endif
+ return &this->vo_driver;
+}
+
+static vo_info_t vo_info_dxr3 = {
+ 2, /* api version */
+ "dxr3enc",
+ "xine mpeg1 encoding video output plugin for dxr3 cards",
+ VISUAL_TYPE_X11,
+ 10 /* priority */
+};
+
+vo_info_t *get_video_out_plugin_info()
+{
+ return &vo_info_dxr3;
+}
+
diff --git a/src/dxr3/dxr3_vo_encoder.h b/src/dxr3/dxr3_vo_encoder.h
new file mode 100644
index 000000000..59c281871
--- /dev/null
+++ b/src/dxr3/dxr3_vo_encoder.h
@@ -0,0 +1,52 @@
+
+/*************************************************************************
+ * Dxr3 Encoding Plugin Configuration Options *
+ *************************************************************************/
+
+/* 1: enable to buffer the mpeg1 stream;
+ * 0: write to mpeg device immediately;
+ * with 1 sync is better, but playback still not smooth (but see below) */
+#define USE_MPEG_BUFFER 1
+
+/* 1: write 6 to MV_COMMAND register. This seems to fix playback problems!
+ * 0: don't write to register */
+#define USE_MAGIC_REGISTER 1
+
+/* 1: use libfame for encoding
+ * 0: use libavcodec from ffmpeg for encoding */
+#define USE_LIBFAME 1
+
+/*************************************************************************
+ * Dxr3 Encoding private stuff below - You shouldn't need to change this *
+ *************************************************************************/
+
+/* buffer size for encoded mpeg1 stream; will hold one intra frame
+ * at 640x480 typical sizes are <50 kB. 512 kB should be plenty */
+#define DEFAULT_BUFFER_SIZE 512*1024
+
+#if USE_LIBFAME
+ # define USE_FFMPEG 0
+#else
+ # define USE_FFMPEG 1
+#endif
+
+#if USE_LIBFAME
+ #include <fame.h>
+
+ /* some global stuff for libfame, could use some cleanup :-) */
+ fame_parameters_t fp = FAME_PARAMETERS_INITIALIZER;
+ fame_object_t *object;
+ fame_yuv_t yuv;
+ fame_context_t *fc; /* needed for fame calls */
+#endif
+
+#if USE_FFMPEG
+ /* use libffmpeg */
+ #include <ffmpeg/avcodec.h>
+ AVCodecContext *avc;
+ AVPicture avp;
+ AVCodec *avcodec;
+#endif
+
+/* mpeg1 buffer, used by both encoders */
+unsigned char *buffer;
diff --git a/src/dxr3/dxr3_vo_standard.c b/src/dxr3/dxr3_vo_standard.c
new file mode 100644
index 000000000..76419e416
--- /dev/null
+++ b/src/dxr3/dxr3_vo_standard.c
@@ -0,0 +1,219 @@
+/*******************************************************************
+ * Dummy video out plugin for the dxr3. Is responsible for setting *
+ * tv_mode, bcs values, setting up the overlay (if enabled), *
+ * and the aspectratio. *
+ * *
+ * All general functions have been moved to dxr3_vo_core.c. *
+ Functions and globals included here (in order of appearance):
+ dxr3_get_capabilities
+ dummy_frame_copy
+ dummy_frame_field
+ dummy_frame_dispose
+ dxr3_alloc_frame
+ dxr3_update_frame_format
+ dxr3_display_frame
+ dxr3_overlay_blend
+ dxr3_exit
+ init_video_out_plugin
+ vo_info_dxr3
+ get_video_out_plugin_info
+ ********************************************************************/
+
+/* Dxr3 videoout globals */
+#include "dxr3_video_out.h"
+
+static uint32_t dxr3_get_capabilities (vo_driver_t *this_gen)
+{
+ /* Since we have no vo format, we return dummy values here */
+ return VO_CAP_YV12 | IMGFMT_YUY2 |
+ VO_CAP_SATURATION | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST;
+}
+
+/* This are dummy functions to fill in the frame object */
+static void dummy_frame_copy (vo_frame_t *vo_img, uint8_t **src)
+{
+ fprintf(stderr, "dxr3_vo: This plugin doesn't play non-mpeg video!\n");
+}
+
+static void dummy_frame_field (vo_frame_t *vo_img, int which_field)
+{
+ fprintf(stderr, "dxr3_vo: This plugin doesn't play non-mpeg video!\n");
+}
+
+static void dummy_frame_dispose (vo_frame_t *frame_gen)
+{
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+
+ if (frame->mem[0])
+ free (frame->mem[0]);
+ if (frame->mem[1])
+ free (frame->mem[1]);
+ if (frame->mem[2])
+ free (frame->mem[2]);
+ free(frame);
+}
+
+static vo_frame_t *dxr3_alloc_frame (vo_driver_t *this_gen)
+{
+ dxr3_frame_t *frame;
+
+ frame = (dxr3_frame_t *) malloc (sizeof (dxr3_frame_t));
+ memset (frame, 0, sizeof(dxr3_frame_t));
+
+ frame->vo_frame.copy = dummy_frame_copy;
+ frame->vo_frame.field = dummy_frame_field;
+ frame->vo_frame.dispose = dummy_frame_dispose;
+
+ return (vo_frame_t*) frame;
+}
+
+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)
+{
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+ int image_size = -1;
+
+ if ((frame->width != width) || (frame->height != height)
+ || (frame->format != format)) {
+
+ if (frame->mem[0]) {
+ free (frame->mem[0]);
+ frame->mem[0] = NULL;
+ }
+ if (frame->mem[1]) {
+ free (frame->mem[1]);
+ frame->mem[1] = NULL;
+ }
+ if (frame->mem[2]) {
+ free (frame->mem[2]);
+ frame->mem[2] = NULL;
+ }
+
+ frame->width = width;
+ frame->height = height;
+ frame->format = format;
+
+ if(flags == 6667){ /* dxr3 flag anyone? :) */
+ int aspect;
+ this->video_width = width;
+ this->video_height = height;
+ this->video_aspect = ratio_code;
+
+ 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);
+ }
+
+ if (format == IMGFMT_YV12) {
+ image_size = width * height;
+ frame->vo_frame.base[0] = malloc_aligned(16,image_size,
+ (void**) &frame->mem[0]);
+ frame->vo_frame.base[1] = malloc_aligned(16,image_size/4,
+ (void**) &frame->mem[1]);
+ frame->vo_frame.base[2] = malloc_aligned(16,image_size/4,
+ (void**) &frame->mem[2]);
+ }else if (format == IMGFMT_YUY2) {
+ frame->vo_frame.base[0] = malloc_aligned(16, image_size*2,
+ (void**)&frame->mem[0]);
+ frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0;
+ }
+ }
+}
+
+static void dxr3_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
+{
+ /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
+ dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen;
+
+ frame->vo_frame.displayed (&frame->vo_frame);
+}
+
+static void dxr3_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
+ vo_overlay_t *overlay)
+{
+ /* dxr3_driver_t *this = (dxr3_driver_t *) this_gen; */
+ fprintf(stderr, "dxr3_vo: dummy function dxr3_overlay_blend called!\n");
+}
+
+void dxr3_exit (vo_driver_t *this_gen)
+{
+ dxr3_driver_t *this = (dxr3_driver_t *) this_gen;
+
+
+ if(this->overlay_enabled)
+ dxr3_overlay_set_mode(&this->overlay, EM8300_OVERLAY_MODE_OFF );
+ close(this->fd_control);
+}
+
+vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)
+{
+ dxr3_driver_t *this;
+
+ /*
+ * allocate plugin struct
+ */
+
+ 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.exit = dxr3_exit;
+ this->config = config;
+
+ /* open control device */
+ devname = config->lookup_str (config, LOOKUP_DEV, DEFAULT_DEV);
+ if ((this->fd_control = open(devname, O_WRONLY)) < 0) {
+ fprintf(stderr, "dxr3_vo: Failed to open control device %s (%s)\n",
+ devname, strerror(errno));
+ return 0;
+ }
+
+ gather_screen_vars(this, visual_gen);
+
+ /* default values */
+ this->overlay_enabled = 0;
+ this->aspectratio = ASPECT_FULL;
+
+ dxr3_read_config(this);
+
+ 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 = {
+ 2, /* api version */
+ "dxr3",
+ "xine dummy video output plugin for dxr3 cards",
+ VISUAL_TYPE_X11,
+ 20 /* priority */
+};
+
+vo_info_t *get_video_out_plugin_info()
+{
+ return &vo_info_dxr3;
+}
+