diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dxr3/Makefile.am | 8 | ||||
-rw-r--r-- | src/dxr3/dxr3.h | 7 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_spu.c | 21 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_video.c | 14 | ||||
-rw-r--r-- | src/dxr3/dxr3_mpeg_encoders.c | 543 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.c | 9 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.h | 5 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.c | 648 | ||||
-rw-r--r-- | src/dxr3/dxr3_video_out.h | 192 | ||||
-rw-r--r-- | src/dxr3/dxr3_vo_core.c | 801 | ||||
-rw-r--r-- | src/dxr3/mpeg_encoders.c | 453 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.c | 1221 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.h | 132 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.c | 11 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 9 |
15 files changed, 1953 insertions, 2121 deletions
diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index ae9d535c7..d0fc11bc2 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -22,13 +22,11 @@ xineplug_decode_dxr3_video_la_LDFLAGS = -avoid-version -module xineplug_decode_dxr3_spu_la_SOURCES = dxr3_decode_spu.c nav_read.c xineplug_decode_dxr3_spu_la_LDFLAGS = -avoid-version -module -xineplug_vo_out_dxr3_la_SOURCES = dxr3_video_out.c \ - dxr3_vo_core.c mpeg_encoders.c alphablend.c +xineplug_vo_out_dxr3_la_SOURCES = video_out_dxr3.c dxr3_mpeg_encoders.c alphablend.c xineplug_vo_out_dxr3_la_LIBADD = $(X_LIBS) -lXext -xineplug_vo_out_dxr3_la_LDFLAGS = -avoid-version \ - -module $(link_fame) $(link_rte) $(X_LIBS) +xineplug_vo_out_dxr3_la_LDFLAGS = -avoid-version -module $(link_fame) $(link_rte) $(X_LIBS) -noinst_HEADERS = dxr3.h dxr3_scr.h dxr3_video_out.h nav_types.h nav_read.h alphablend.h bswap.h +noinst_HEADERS = dxr3.h dxr3_scr.h video_out_dxr3.h nav_types.h nav_read.h alphablend.h bswap.h debug: @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(LINUX_INCLUDE)" diff --git a/src/dxr3/dxr3.h b/src/dxr3/dxr3.h index f6d3cc2d9..c17708e11 100644 --- a/src/dxr3/dxr3.h +++ b/src/dxr3/dxr3.h @@ -17,9 +17,12 @@ * 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 $ + * $Id: dxr3.h,v 1.2 2002/05/24 22:09:44 miguelfreitas Exp $ */ +#ifndef HAVE_DXR3_H +#define HAVE_DXR3_H + #include <linux/em8300.h> /* data for the device name config entry */ @@ -30,3 +33,5 @@ /* image format used by dxr3_decoder to tag undecoded mpeg data */ #define IMGFMT_MPEG (('G'<<24)|('E'<<16)|('P'<<8)|'M') + +#endif diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c index 3b9b78f8a..31649cf62 100644 --- a/src/dxr3/dxr3_decode_spu.c +++ b/src/dxr3/dxr3_decode_spu.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_decode_spu.c,v 1.2 2002/05/06 11:26:37 jcdutton Exp $ + * $Id: dxr3_decode_spu.c,v 1.3 2002/05/24 22:09:44 miguelfreitas Exp $ */ /* dxr3 spu decoder plugin. @@ -26,7 +26,6 @@ * Takes precedence over libspudec due to a higher priority. */ - #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> @@ -82,10 +81,10 @@ typedef struct dxr3_spudec_s { char devname[128]; char devnum[3]; - int fd_spu; /* to access the dxr3 spu device */ + 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? */ + int menu; /* are we in a menu? */ pci_t pci; uint32_t buttonN; /* currently highlighted button */ } dxr3_spudec_t; @@ -94,7 +93,7 @@ typedef struct dxr3_spudec_s { spu_decoder_t *init_spu_decoder_plugin(int iface_version, xine_t *xine) { dxr3_spudec_t *this; - char *confstr; + const char *confstr; int dashpos; if (iface_version != 7) { @@ -108,6 +107,7 @@ spu_decoder_t *init_spu_decoder_plugin(int iface_version, xine_t *xine) if (!dxr3_present(xine)) return NULL; this = (dxr3_spudec_t *)malloc(sizeof(dxr3_spudec_t)); + if (!this) return NULL; confstr = xine->config->register_string(xine->config, CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, NULL, NULL); @@ -195,7 +195,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) printf("dxr3_decode_spu: failed to set CLUT (%s)\n", strerror(errno)); return; } - if(buf->type == BUF_SPU_SUBP_CONTROL) { + 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; @@ -230,9 +230,18 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) } if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci.hli.hl_gi.hli_ss == 1)) { + /* this is (or: should be, I hope I got this right) a + subpicture plane, that hides all menu buttons */ + uint8_t empty_spu[] = { + 0x00, 0x26, 0x00, 0x08, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x20, 0x01, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x06, 0x00, 0x04, 0x00, 0x07, 0xFF, + 0x00, 0x01, 0x00, 0x20, 0x02, 0xFF }; /* leaving menu */ this->pci.hli.hl_gi.hli_ss = 0; ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, NULL); + write(this->fd_spu, empty_spu, sizeof(empty_spu)); } } return; diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c index cb6bbfdb7..10c07700e 100644 --- a/src/dxr3/dxr3_decode_video.c +++ b/src/dxr3/dxr3_decode_video.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_decode_video.c,v 1.2 2002/05/06 11:26:37 jcdutton Exp $ + * $Id: dxr3_decode_video.c,v 1.3 2002/05/24 22:09:44 miguelfreitas Exp $ */ /* dxr3 video decoder plugin. @@ -26,7 +26,6 @@ * due to a higher priority. */ - #include <sys/types.h> #include <sys/ioctl.h> #include <stdio.h> @@ -102,6 +101,8 @@ 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); + +/* config callbacks */ 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); @@ -111,7 +112,7 @@ video_decoder_t *init_video_decoder_plugin(int iface_version, xine_t *xine) { dxr3_decoder_t *this; config_values_t *cfg; - char *tmpstr; + const char *confstr; int dashpos; if (iface_version != 8) { @@ -125,10 +126,11 @@ video_decoder_t *init_video_decoder_plugin(int iface_version, xine_t *xine) if (!dxr3_present(xine)) return NULL; this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t)); + if (!this) return NULL; cfg = xine->config; - tmpstr = cfg->register_string(cfg, CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, NULL, NULL); - strncpy(this->devname, tmpstr, 128); + confstr = cfg->register_string(cfg, 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] == '-') { @@ -240,7 +242,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) */ buffer = buf->content; shift = 0xffffff00; - for (i=0; i<buf->size; i++) { + for (i = 0; i < buf->size; i++) { byte = *buffer++; if (shift != 0x00000100) { shift = (shift | byte) << 8; diff --git a/src/dxr3/dxr3_mpeg_encoders.c b/src/dxr3/dxr3_mpeg_encoders.c new file mode 100644 index 000000000..4dfc4cccb --- /dev/null +++ b/src/dxr3/dxr3_mpeg_encoders.c @@ -0,0 +1,543 @@ +/* + * 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_mpeg_encoders.c,v 1.1 2002/05/24 22:09:44 miguelfreitas Exp $ + */ + +/* mpeg encoders for the dxr3 video out plugin. + * supports the libfame and librte mpeg encoder libraries. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_LIBRTE +# define _GNU_SOURCE +# include <unistd.h> +# include <rte.h> +#endif +#ifdef HAVE_LIBFAME +# include <fame.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> + +#include "xineutils.h" +#include "video_out_dxr3.h" + +#define LOG_ENC 1 + +/* 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 + + +#ifdef HAVE_LIBRTE +/* initialization function */ +int dxr3_rte_init(dxr3_driver_t *drv); + +/* functions required by encoder api */ +static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int rte_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int rte_on_close(dxr3_driver_t *drv); + +/* helper function */ +static void mp1e_callback(rte_context *context, void *data, ssize_t size, + void *user_data); + +/* encoder structure */ +typedef struct rte_data_s { + encoder_data_t encoder_data; + rte_context *context; /* handle for encoding */ + int width, height; + void *rte_ptr; /* buffer maintened by librte */ + double rte_bitrate; /* mpeg out bitrate, default 2.3e6 bits/s */ +} rte_data_t; +#endif + +#ifdef HAVE_LIBFAME +/* initialization function */ +int dxr3_fame_init(dxr3_driver_t *drv); + +/* functions required by encoder api */ +static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int fame_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame); +static int fame_on_close(dxr3_driver_t *drv); + +/* encoder structure */ +typedef struct { + encoder_data_t encoder_data; + fame_context_t *context; /* needed for fame calls */ + fame_parameters_t fp; + fame_yuv_t yuv; + char *buffer; /* temporary buffer for mpeg data */ + /* temporary buffer for YUY2->YV12 conversion */ + uint8_t *out[3]; /* aligned buffer for YV12 data */ + uint8_t *buf; /* unaligned YV12 buffer */ +} fame_data_t; + +/* helper function */ +static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, + dxr3_frame_t *frame); +#endif + + +#ifdef HAVE_LIBRTE +int dxr3_rte_init(dxr3_driver_t *drv) +{ + rte_data_t* this; + + if (!rte_init()) { + printf("dxr3_mpeg_encoder: failed to init librte\n"); + return 0; + } + + this = malloc(sizeof(rte_data_t)); + if (!this) return 0; + memset(this, 0, sizeof(rte_data_t)); + + this->encoder_data.type = ENC_RTE; + this->encoder_data.on_update_format = rte_on_update_format; + this->encoder_data.on_frame_copy = NULL; + this->encoder_data.on_display_frame = rte_on_display_frame; + this->encoder_data.on_close = rte_on_close; + this->context = 0; + + drv->enc = &this->encoder_data; + return 1; +} + +static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + rte_data_t *this = (rte_data_t *)drv->enc; + rte_context *context; + rte_codec *codec; + double fps; + + if (this->context) { /* already running */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: closing current encoding context.\n"); +#endif + rte_stop(this->context); + rte_context_destroy(this->context); + this->context = 0; + } + + this->width = drv->video_width; + this->height = drv->video_oheight; + + /* create new rte context */ + this->context = rte_context_new(this->width, this->height, "mp1e", drv); + if (!this->context) { + printf("dxr3_mpeg_encoder: failed to get rte context.\n"); + return 0; + } + context = this->context; /* shortcut */ +#if LOG_ENC + rte_set_verbosity(context, 2); +#endif + + /* get mpeg codec handle */ + codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1_video"); + if (!codec) { + printf("dxr3_mpeg_encoder: could not create codec.\n"); + rte_context_destroy(context); + this->context = 0; + return 0; + } + + this->rte_bitrate = drv->config->register_range(drv->config, + "dxr3.rte_bitrate", 10000, 1000, 20000, + "Dxr3enc: rte mpeg output bitrate (kbit/s)", + "The bitrate the mpeg encoder library librte should use for dxr3's encoding mode", + 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 + */ + fps = 90000.0 / frame->vo_frame.duration; + if (!rte_option_set(codec, "virtual_frame_rate", fps)) + printf("dxr3_mpeg_encoder: WARNING: rte_option_set failed; virtual_frame_rate = %g.\n", fps); + if (!rte_option_set(codec, "coded_frame_rate", fps)) + printf("dxr3_mpeg_encoder: WARNING: rte_option_set failed; coded_frame_rate = %g.\n", fps); + if (!rte_option_set(codec, "bit_rate", (int)this->rte_bitrate)) + printf("dxr3_mpeg_encoder: WARNING: rte_option_set failed; bit_rate = %d.\n", (int)this->rte_bitrate); + if (!rte_option_set(codec, "gop_sequence", "I")) + printf("dxr3_mpeg_encoder: 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_mpeg_encoder: WARNING: rte_option_set failed; motion_compensation = 0.\n"); + + rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL); + rte_set_output(context, mp1e_callback, NULL, NULL); + + if (!rte_init_context(context)) { + printf("dxr3_mpeg_encoder: cannot init the context: %s\n", context->error); + rte_context_destroy(context); + this->context = 0; + return 0; + } + /* do the sync'ing and start encoding */ + if (!rte_start_encoding(context)) { + printf("dxr3_mpeg_encoder: cannot start encoding: %s\n", context->error); + rte_context_destroy(context); + this->context = 0; + return 0; + } + this->rte_ptr = rte_push_video_data(context, NULL, 0); + if (!this->rte_ptr) { + printf("dxr3_mpeg_encoder: failed to get encoder buffer pointer.\n"); + return 0; + } + + /* set the dxr3 playmode */ + if (drv->enhanced_mode) { + em8300_register_t regs; + regs.microcode_register = 1; + regs.reg = 0; + regs.val = MVCOMMAND_SYNC; + ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, ®s); + } + + return 1; +} + +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 1; + + 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_ptr = rte_push_video_data(this->context, this->rte_ptr, + frame->vo_frame.vpts / 90000.0); + + frame->vo_frame.displayed(&frame->vo_frame); + return 1; +} + +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_destroy(this->context); + } + free(this); + drv->enc = 0; + return 1; +} + + +static void mp1e_callback(rte_context *context, void *data, ssize_t size, void *user_data) +{ + dxr3_driver_t *drv = (dxr3_driver_t *)user_data; + char tmpstr[128]; + ssize_t written; + + 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) return; + written = write(drv->fd_video, data, size); + if (written < 0) { + printf("dxr3_mpeg_encoder: video device write failed (%s)\n", + strerror(errno)); + return; + } + if (written != size) + printf("dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", + written, size); +} +#endif + + +#ifdef HAVE_LIBFAME +int dxr3_fame_init(dxr3_driver_t *drv) +{ + fame_data_t *this; + + this = malloc(sizeof(fame_data_t)); + if (!this) return 0; + memset(this, 0, sizeof(fame_data_t)); + + this->encoder_data.type = ENC_FAME; + 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; + this->context = 0; + + drv->enc = &this->encoder_data; + return 1; +} + +static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + fame_data_t *this = (fame_data_t *)drv->enc; + fame_parameters_t init_fp = FAME_PARAMETERS_INITIALIZER; + double fps; + + if (this->buf) free(this->buf); + this->buf = 0; + this->out[0] = this->out[1] = this->out[2] = 0; + + /* if YUY2 and dimensions changed, we need to re-allocate the + * internal YV12 buffer */ + if (drv->format == IMGFMT_YUY2) { + int image_size = drv->video_width * drv->video_oheight; + + this->out[0] = xine_xmalloc_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); +#if LOG_ENC + printf("dxr3_mpeg_encoder: Using YUY2->YV12 conversion\n"); +#endif + } + + if (this->context) { +#if LOG_ENC + printf("dxr3_mpeg_encoder: closing current encoding context.\n"); +#endif + fame_close(this->context); + this->context = 0; + } + + this->context = fame_open(); + if (!this->context) { + printf("dxr3_mpeg_encoder: Couldn't start the FAME library\n"); + return 0; + } + + if (!this->buffer) + this->buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); + if (!this->buffer) { + printf("dxr3_mpeg_encoder: Couldn't allocate temp buffer for mpeg data\n"); + return 0; + } + + this->fp = init_fp; + this->fp.quality = drv->config->register_range(drv->config, + "dxr3.fame_quality", 90, 10, 100, + "Dxr3enc: fame mpeg encoding quality", + "The encoding quality of the libfame mpeg encoder library.", + NULL,NULL); +#if LOG_ENC + /* 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_mpeg_encoder: quality %d -> quant scale = %d\n", this->fp.quality, + 1 + (30 * (100 - this->fp.quality) + 50) / 100); +#endif + this->fp.width = drv->video_width; + this->fp.height = drv->video_oheight; + this->fp.profile = "mpeg1"; + this->fp.coding = "I"; +#if LOG_ENC + this->fp.verbose = 1; +#else + this->fp.verbose = 0; +#endif + + /* start guessing the framerate */ + fps = 90000.0 / frame->vo_frame.duration; + if (fabs(fps - 25) < 0.01) { /* PAL */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to PAL (25 Hz)\n"); +#endif + this->fp.frame_rate_num = 25; + this->fp.frame_rate_den = 1; + } + else if (fabs(fps - 24) < 0.01) { /* FILM */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to FILM (24 Hz)\n"); +#endif + this->fp.frame_rate_num = 24; + this->fp.frame_rate_den = 1; + } + else if (fabs(fps - 23.976) < 0.01) { /* NTSC-FILM */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to NTSC-FILM (23.976 Hz)\n"); +#endif + this->fp.frame_rate_num = 24000; + this->fp.frame_rate_den = 1001; + } + else if (fabs(fps - 29.97) < 0.01) { /* NTSC */ +#if LOG_ENC + printf("dxr3_mpeg_encoder: setting mpeg output framerate to NTSC (29.97 Hz)\n"); +#endif + 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; +#if LOG_ENC + printf("dxr3_mpeg_encoder: trying to set mpeg output framerate to %d Hz\n", + this->fp.frame_rate_num); +#endif + } + + fame_init (this->context, &this->fp, this->buffer, DEFAULT_BUFFER_SIZE); + + /* set the dxr3 playmode */ + if (drv->enhanced_mode) { + em8300_register_t regs; + regs.microcode_register = 1; + regs.reg = 0; + regs.val = MVCOMMAND_SYNC; + ioctl(drv->fd_control, EM8300_IOCTL_WRITEREG, ®s); + } + + return 1; +} + +static int fame_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + fame_data_t *this = (fame_data_t *)drv->enc; + char tmpstr[128]; + ssize_t written; + int size; + + if ((frame->width != this->fp.width) || (frame->oheight != this->fp.height)) + /* probably an old frame for a previous context. ignore it */ + return 1; + + fame_prepare_frame(this, drv, frame); + size = fame_encode_frame(this->context, &this->yuv, NULL); + frame->vo_frame.displayed(&frame->vo_frame); + + 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) return 0; + written = write(drv->fd_video, this->buffer, size); + if (written < 0) { + printf("dxr3_mpeg_encoder: video device write failed (%s)\n", + strerror(errno)); + return 0; + } + if (written != size) + printf("dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", + written, size); + return 1; +} + +static int fame_on_close(dxr3_driver_t *drv) +{ + fame_data_t *this = (fame_data_t *)drv->enc; + + if (this->context) + fame_close(this->context); + free(this); + drv->enc = 0; + return 1; +} + + +static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame) +{ + int i, j, w2; + uint8_t *y, *u, *v, *yuy2; + + if (frame->vo_frame.bad_frame) return 1; + + if (frame->vo_frame.format == IMGFMT_YUY2) { + /* need YUY2->YV12 conversion */ + if (!(this->out[0] && this->out[1] && this->out[2]) ) { + printf("dxr3_mpeg_encoder: Internal YV12 buffer not created.\n"); + return 0; + } + 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->iheight; 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 1; +} +#endif diff --git a/src/dxr3/dxr3_scr.c b/src/dxr3/dxr3_scr.c index 2ddfb6844..97cfb9bdf 100644 --- a/src/dxr3/dxr3_scr.c +++ b/src/dxr3/dxr3_scr.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_scr.c,v 1.1 2002/05/06 11:26:37 jcdutton Exp $ + * $Id: dxr3_scr.c,v 1.2 2002/05/24 22:09:44 miguelfreitas Exp $ */ /* dxr3 scr plugin. @@ -25,17 +25,14 @@ * 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 @@ -51,13 +48,15 @@ static void dxr3_scr_exit(scr_plugin_t *scr); /* helper function */ static int dxr3_mvcommand(int fd_control, int command); + +/* config callback */ 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; + const char *confstr; this = (dxr3_scr_t *)malloc(sizeof(dxr3_scr_t)); diff --git a/src/dxr3/dxr3_scr.h b/src/dxr3/dxr3_scr.h index b0814ebd8..8260ce3f0 100644 --- a/src/dxr3/dxr3_scr.h +++ b/src/dxr3/dxr3_scr.h @@ -17,9 +17,12 @@ * 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 $ + * $Id: dxr3_scr.h,v 1.2 2002/05/24 22:09:44 miguelfreitas Exp $ */ +#include "xine_internal.h" + + /* plugin structure */ typedef struct dxr3_scr_s { scr_plugin_t scr_plugin; diff --git a/src/dxr3/dxr3_video_out.c b/src/dxr3/dxr3_video_out.c deleted file mode 100644 index 29edf5c5e..000000000 --- a/src/dxr3/dxr3_video_out.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * 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_video_out.c,v 1.16 2002/05/06 11:26:37 jcdutton 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. - * - ***** Update 1/12/2001 by Harm - * some support for mp1e encoder. Needs the raw-input patch for mp1e to - * be functional. I'm sending that patch to the mp1e guys at zapping.sf.net, - * it might be in the next version... - * - * (later) A/V sync should now be good; MP1E_DISPLAY_FRAME==1 works. - * needs major code cleanup, but that's for later. - * - * looks like it'll work with mp1e rte API as well, provided it's - * stable and all threads don't become a tangled mess. - * - ****** Update 2/12/2001 by Harm - * - * Switched to librte instead of that weird mp1e-fifo concoction. - * Not terribly impressed by the speed gain, if any, but certainly - * cleaner. To use it, install librte-0.4 (get it at zapping.sf.net, the - * API is still under development so don't expect newer versions to work - * right away), define USE_MP1E 1 in the header below and change -lfame - * to -lrte in Makefile.am - * - ****** Update 11/12/2001 by Harm - * - * Much much needed clean up. - * Dropped ffmpeg support for the moment. Moved almost all libfame and - * librte stuff in separate sections, defined general encoder API - * in encoder_data_t. - * - ****** Update 16/12/2001 by Harm - * - * Merged dxr3 and dxr3enc video out drivers. Now there's only one! - * dxr3_vo_standard.c and dxr3_vo_encoder.c are no more, everything - * is in dxr3_video_out.c. - * - * renamed most config variables dxr3enc.XXX to dxr3.XXX - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "dxr3_video_out.h" - -#ifdef HAVE_LIBRTE -int dxr3_rte_init(dxr3_driver_t *); -#endif -#ifdef HAVE_LIBFAME -int dxr3_fame_init(dxr3_driver_t *); -#endif - -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; -} - -static void dummy_frame_field (vo_frame_t *vo_img, int which_field) -{ - /* dummy function */ -} - -static void dxr3_frame_dispose (vo_frame_t *frame_gen) -{ - dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen; - if (frame->mem) - free (frame->mem); - 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_frame_t *frame; - dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - - frame = (dxr3_frame_t *) malloc (sizeof (dxr3_frame_t)); - memset (frame, 0, sizeof(dxr3_frame_t)); - - if (this->enc && this->enc->on_frame_copy) - frame->vo_frame.copy = dxr3_frame_copy; - else - frame->vo_frame.copy = 0; - frame->vo_frame.field = dummy_frame_field; - frame->vo_frame.dispose = dxr3_frame_dispose; - frame->vo_frame.driver = this_gen; - - return (vo_frame_t*) frame; -} - -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,i; - dxr3_frame_t *frame = (dxr3_frame_t *) frame_gen; - int image_size, oheight; - - /* update the overlay window co-ords if required */ - dxr3_overlay_update(this); - - /* reset the copy calls counter (number of calls to dxr3_frame_copy) */ - frame->copy_calls = 0; - frame->vo_frame.driver = this_gen; - - aspect = this->aspectratio; - 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; - } - - /* 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; - } - - if (this->add_bars == 0) { - /* 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 */ - 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("dxr3: adding %d black lines to get %s a.r.\n", - oheight-height, aspect == ASPECT_FULL ? "4:3" : "16:9"); - this->video_width = width; - this->video_iheight = height; - this->video_height = oheight; - this->video_aspect = ratio_code; - this->fps = 90000.0/frame->vo_frame.duration; - this->format = format; - this->need_redraw = 1; - - 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" - ); - } - - if (this->enc && this->enc->on_update_format) - this->enc->on_update_format(this); - } - - - /* if dimensions changed, we need to re-allocate frame memory */ - if ((frame->width != width) || (frame->height != height) || - (frame->oheight != oheight)) { - if (frame->mem) { - free (frame->mem); - frame->mem = NULL; - } - /* make top black bar multiple of 16, - * so old and new macroblocks overlap */ - this->top_bar = ((oheight - height) / 32) * 16; - if (format == IMGFMT_YUY2) { - image_size = width * oheight; /* includes black bars */ - /* 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); - /* don't use first line */ - frame->real_base[0] += width * 2; - frame->real_base[1] = frame->real_base[2] = 0; - - /* fix offset, so the decoder does not see the top black bar */ - frame->vo_frame.base[0] = frame->real_base[0] + width * 2 * this->top_bar; - frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0; - - /* 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 */ - } - else { /* IMGFMT_YV12 */ - image_size = width * oheight; /* includes black bars */ - /* add one extra line for field swap stuff */ - frame->real_base[0] = malloc_aligned(16, (image_size + width) * 3/2, - (void**) &frame->mem); - /* don't use first line */ - frame->real_base[0] += width; - frame->real_base[1] = frame->real_base[0] + image_size; - frame->real_base[2] = frame->real_base[1] + image_size/4; - - /* 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 * this->top_bar; - frame->vo_frame.base[1] = frame->real_base[1] + width * this->top_bar/4; - frame->vo_frame.base[2] = frame->real_base[2] + width * this->top_bar/4; - } - } - - 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; - } - } - - frame->width = width; - frame->height = height; - frame->oheight = oheight; - frame->swap_fields = this->swap_fields; - if(this->aspectratio!=aspect) - dxr3_set_property (this_gen,VO_PROP_ASPECT_RATIO, aspect); - -} - -int dxr3_redraw_needed(vo_driver_t *this_gen) -{ - dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - - dxr3_overlay_update(this); - - if (this->need_redraw) { - this->need_redraw = 0; - return 1; - } - - 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); -} - -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; - - if (frame_gen->format != IMGFMT_MPEG && this->enc && this->enc->on_display_frame) { - this->enc->on_display_frame(this, frame); - } else { - frame_gen->displayed(frame_gen); - } - /* for non-mpeg, the encoder plugin is responsible for calling - * frame_gen->displayed(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); - } - } -} - -void dxr3_exit (vo_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->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")); -} - -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")); -} - -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")); -} - -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 - */ -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; - } - /* 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: "); -#ifdef HAVE_LIBFAME - 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) "); -#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); -#ifdef HAVE_LIBRTE - 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; -#endif - 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( -"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; -} - -static vo_info_t vo_info_dxr3 = { - 5, /* api version */ - "dxr3", - "xine 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_video_out.h b/src/dxr3/dxr3_video_out.h deleted file mode 100644 index 31e28971b..000000000 --- a/src/dxr3/dxr3_video_out.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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_video_out.h,v 1.20 2002/05/06 11:26:37 jcdutton Exp $ - * - */ - -/* - * 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" -#include "alphablend.h" - -/* for fast_memcpy: */ -#include "xineutils.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.devicename" -#define DEFAULT_DEV "/dev/em8300" - -/* image format used by dxr3_decoder to tag undecoded mpeg data */ -#define IMGFMT_MPEG (('G'<<24)|('E'<<16)|('P'<<8)|'M') - -/* values for fd_video indicating why it is closed */ -#define CLOSED_FOR_DECODER -1 -#define CLOSED_FOR_ENCODER -2 - -struct coeff { - 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]; -} 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, - 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); -*/ -} 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*/ -} 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 *); -}; - -/* func definitions */ -int dxr3_redraw_needed(vo_driver_t *this_gen); - -/* 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_adapt_area(dxr3_driver_t *this, - 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); -void dxr3_get_keycolor(dxr3_driver_t *this); -void dxr3_read_config(dxr3_driver_t *this, void *visual_gen); - -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 deleted file mode 100644 index dbcd96316..000000000 --- a/src/dxr3/dxr3_vo_core.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * 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_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 * - *************************************************************************/ - -#include "dxr3_video_out.h" -#include <locale.h> - -/* -#define OVERLAY_LOG 1 -*/ - -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; -} - -/****** 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, - 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); - } - } -} - - -/****** 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, 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)); - - 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->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); - 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."); -} - - -/******** 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; -} - - -/******* 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=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) -{ - 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) -{ - /* 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; - - - if (!this->overlay_enabled && !this->tv_switchable) return 0; - - 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 - * 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_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; -#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->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); -} - -/************************************************************************** - * 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; -#if OVERLAY_LOG - printf("dxr3: found parameter \"%s\"\n", name); -#endif - return 1; - } -#if OVERLAY_LOG - printf("dxr3: WARNING: unknown parameter \"%s\"\n", name); -#endif - 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); -#if OVERLAY_LOG - 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 OVERLAY_LOG - printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr); -#endif - break; - case TYPE_XINT: - sscanf(tok,"%x",(int *)ptr); -#if OVERLAY_LOG - printf("dxr3: value \"%s\" -> %d\n", tok, *(int*)ptr); -#endif - break; - case TYPE_FLOAT: - sscanf(tok,"%f",(float *)ptr); -#if OVERLAY_LOG - 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); -#if OVERLAY_LOG - 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); -#if OVERLAY_LOG - 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; -} - -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; - -#if OVERLAY_LOG - 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]); - -#if OVERLAY_LOG - 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]); -#if OVERLAY_LOG - 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; -} - - -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/mpeg_encoders.c b/src/dxr3/mpeg_encoders.c deleted file mode 100644 index 841a9d8ae..000000000 --- a/src/dxr3/mpeg_encoders.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * 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: mpeg_encoders.c,v 1.7 2002/05/06 11:26:37 jcdutton Exp $ - * - * mpeg encoders for the dxr3 video out plugin. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_LIBRTE -# define _GNU_SOURCE -# include <unistd.h> -# include <rte.h> -#endif -#ifdef HAVE_LIBFAME -# include <fame.h> -#endif - -#include "dxr3_video_out.h" - -#define MV_COMMAND 0 -/* 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 - -#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 */ -} rte_data_t; - - -static void mp1e_callback(rte_context *context, void *data, ssize_t size, - void* user_data) -{ - dxr3_driver_t *this = (dxr3_driver_t*)user_data; - em8300_register_t regs; - char tmpstr[128]; - - if (this->enhanced_mode) - { - 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); - } - if (this->fd_video == CLOSED_FOR_ENCODER) { - snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum); - this->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK); - } - if (this->fd_video < 0) return; - /* FIXME: Is a SETPTS necessary here? */ - if (write(this->fd_video, data, size) < 0) - perror("dxr3: writing to video device"); -} - -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; -} - -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; -} - -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; -} - -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; -} - -#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 */ -} fame_data_t; - - -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; -} - -static int fame_prepare_frame(fame_data_t* this, dxr3_driver_t *drv, - 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; -} - - -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; -} - -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; -} - -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; -} - -#endif - diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c new file mode 100644 index 000000000..507632add --- /dev/null +++ b/src/dxr3/video_out_dxr3.c @@ -0,0 +1,1221 @@ +/* + * 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: video_out_dxr3.c,v 1.20 2002/05/24 22:09:44 miguelfreitas 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> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#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 <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#ifdef HAVE_XINERAMA +# include <X11/extensions/Xinerama.h> +#endif + +#include "xine_internal.h" +#include "xineutils.h" +#include "video_out.h" +#include "../video_out/video_out_x11.h" +#include "alphablend.h" +#include "dxr3.h" +#include "video_out_dxr3.h" + +#define LOG_VID 1 +#define LOG_OVR 0 + + +/* plugin initialization functions */ +vo_info_t *get_video_out_plugin_info(); +vo_driver_t *init_video_out_plugin(config_values_t *config, void *visual_gen); + +/* functions required by xine api */ +static uint32_t dxr3_get_capabilities(vo_driver_t *this_gen); +static vo_frame_t *dxr3_alloc_frame(vo_driver_t *this_gen); +static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src); +static void dxr3_frame_field(vo_frame_t *vo_img, int which_field); +static void dxr3_frame_dispose(vo_frame_t *frame_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); +static void dxr3_overlay_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen, + vo_overlay_t *overlay); +static void dxr3_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen); +static int dxr3_redraw_needed(vo_driver_t *this_gen); +static int dxr3_get_property(vo_driver_t *this_gen, int property); +static int dxr3_set_property(vo_driver_t *this_gen, int property, int value); +static void dxr3_get_property_min_max(vo_driver_t *this_gen, int property, + int *min, int *max); +static int dxr3_gui_data_exchange(vo_driver_t *this_gen, + int data_type, void *data); +static void dxr3_exit(vo_driver_t *this_gen); + +/* overlay helper functions only called once during plugin init */ +static void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis); +static int dxr3_overlay_read_state(dxr3_overlay_t *this); +static int dxr3_overlay_set_keycolor(dxr3_overlay_t *this); +static int dxr3_overlay_set_attributes(dxr3_overlay_t *this); + +/* overlay helper functions */ +static int dxr3_overlay_set_window(dxr3_overlay_t *this, int xpos, int ypos, + int width, int height); +static void dxr3_overlay_update(dxr3_driver_t *this); +static void dxr3_zoomTV(dxr3_driver_t *this); +static void dxr3_translate_gui2video(dxr3_driver_t *this, int x, int y, + int *vid_x, int *vid_y); +static int is_fullscreen(dxr3_driver_t *this); + +/* config callbacks */ +static void dxr3_update_add_bars(void *data, cfg_entry_t *entry); +static void dxr3_update_swap_fields(void *data, cfg_entry_t *entry); +static void dxr3_update_enhanced_mode(void *this_gen, cfg_entry_t *entry); + + +vo_info_t *get_video_out_plugin_info() +{ + static vo_info_t vo_info_dxr3 = { + 5, /* api version */ + "dxr3", + "xine video output plugin for dxr3 cards", + VISUAL_TYPE_X11, + 10 /* priority */ + }; + + return &vo_info_dxr3; +} + +vo_driver_t *init_video_out_plugin(config_values_t *config, void *visual_gen) +{ + dxr3_driver_t *this; + char tmpstr[100]; + char *available_encoders, *default_encoder; + const char *confstr; + int dashpos; + + this = (dxr3_driver_t *)malloc(sizeof(dxr3_driver_t)); + if (!this) 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.overlay_blend = dxr3_overlay_blend; + this->vo_driver.display_frame = dxr3_display_frame; + this->vo_driver.redraw_needed = dxr3_redraw_needed; + 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; + this->aspect = ASPECT_FULL; + this->overlay_enabled = 0; + 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 aspect ratio.", 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 smoother play mode", dxr3_update_enhanced_mode, this); + + confstr = config->register_string(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'; + } + + snprintf(tmpstr, sizeof(tmpstr), "%s%s", this->devname, this->devnum); +#if LOG_VID + printf("video_out_dxr3: Entering video init, devname = %s.\n", tmpstr); +#endif + if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { + printf("video_out_dxr3: Failed to open control device %s (%s)\n", + tmpstr, strerror(errno)); + return 0; + } + + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum); + if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) { + printf("dxr3:Ffailed to open video device %s (%s)\n", + tmpstr, strerror(errno)); + return 0; + } + /* close now and and let the decoder/encoder reopen if they want */ + close(this->fd_video); + this->fd_video = CLOSED_FOR_DECODER; + + /* which encoder to use? Whadda we got? */ + default_encoder = 0; + this->enc = 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) "); +#endif +#ifdef HAVE_LIBRTE + default_encoder = "rte"; + strcat(available_encoders, "\"rte\" (fast, high quality) "); +#endif +#if LOG_VID + printf("video_out_dxr3: %s\n", available_encoders); +#endif + if (default_encoder) { + confstr = config->register_string(config, "dxr3.encoder", + default_encoder, available_encoders, NULL, NULL, NULL); +#ifdef HAVE_LIBRTE + if ((strcmp(confstr, "rte") == 0) && !dxr3_rte_init(this)) + return 0; +#endif +#ifdef HAVE_LIBFAME + if ((strcmp(confstr, "fame") == 0) && !dxr3_fame_init(this)) + return 0; +#endif + if (this->enc == 0) + printf("video_out_dxr3: mpeg encoder \"%s\" not compiled in or not supported.\n" + "video_out_dxr3: valid options are %s\n", confstr, available_encoders); + } + else + printf("video_out_dxr3: no mpeg encoder compiled in.\n" + "video_out_dxr3: that's ok, you don't need it for mpeg video like DVDs, but\n" + "video_out_dxr3: you will not be able to play non-mpeg content using this video out\n" + "video_out_dxr3: driver. See the README.dxr3 for details on configuring an encoder.\n"); + + /* init bcs */ + if (ioctl(this->fd_control, EM8300_IOCTL_GETBCS, &this->bcs)) + printf("video_out_dxr3: 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); + + /* overlay or tvout? */ + confstr = config->register_string(config, "dxr3.videoout_mode", "tv", + "Dxr3: videoout mode (tv or overlay)", NULL, NULL, NULL); +#if LOG_VID + printf("video_out_dxr3: overlaymode = %s\n", confstr); +#endif + if (strcasecmp(confstr, "tv") == 0) { + this->overlay_enabled = 0; + this->tv_switchable = 0; /* don't allow on-the-fly switching */ + } else if (strcasecmp(confstr, "overlay") == 0) { +#if LOG_VID + printf("video_out_dxr3: setting up overlay mode\n"); +#endif + gather_screen_vars(this, visual_gen); + if (dxr3_overlay_read_state(&this->overlay) == 0) { + this->overlay_enabled = 1; + this->tv_switchable = 1; + confstr = config->register_string(config, "dxr3.keycolor", "0x80a040", + "Dxr3: overlay colorkey value", NULL, NULL, NULL); + sscanf(confstr, "%x", &this->overlay.colorkey); + confstr = config->register_string(config, "dxr3.color_interval", "50.0", + "Dxr3: overlay colorkey range", + "A greater value widens the tolerance for the overlay keycolor", NULL, NULL); + sscanf(confstr, "%f", &this->overlay.color_interval); + } else { + printf("video_out_dxr3: please run autocal, overlay disabled\n"); + this->overlay_enabled = 0; + this->tv_switchable = 0; + } + } + + /* init tvmode */ + confstr = config->register_string(config, "dxr3.preferred_tvmode", "default", + "Dxr3 preferred tv mode - PAL, PAL60, NTSC or default", NULL, NULL, NULL); + if (strcasecmp(confstr, "ntsc") == 0) { + this->tv_mode = EM8300_VIDEOMODE_NTSC; +#if LOG_VID + printf("video_out_dxr3: setting tv_mode to NTSC\n"); +#endif + } else if (strcasecmp(confstr, "pal") == 0) { + this->tv_mode = EM8300_VIDEOMODE_PAL; +#if LOG_VID + printf("video_out_dxr3: setting tv_mode to PAL 50Hz\n"); +#endif + } else if (strcasecmp(confstr, "pal60") == 0) { + this->tv_mode = EM8300_VIDEOMODE_PAL60; +#if LOG_VID + printf("video_out_dxr3: setting tv_mode to PAL 60Hz\n"); +#endif + } 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("video_out_dxr3: setting video mode failed.\n"); + + /* initialize overlay */ + if (this->overlay_enabled) { + em8300_overlay_screen_t scr; + + this->overlay.fd_control = this->fd_control; + + /* allocate keycolor */ + 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); + + /* set the screen */ + scr.xsize = this->overlay.screen_xres; + scr.ysize = this->overlay.screen_yres; + if (ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)) + printf("video_out_dxr3: setting the overlay screen failed.\n"); + + if (dxr3_overlay_set_window(&this->overlay, 1, 1, 2, 2) != 0) + printf("video_out_dxr3: setting the overlay window failed.\n"); + if (dxr3_overlay_set_keycolor(&this->overlay) != 0) + printf("video_out_dxr3: setting the overlay keycolor failed.\n"); + if (dxr3_overlay_set_attributes(&this->overlay) != 0) + printf("video_out_dxr3: setting an overlay attribute failed.\n"); + + if (ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, EM8300_OVERLAY_MODE_OVERLAY) != 0) + printf("video_out_dxr3: failed to enable overlay.\n"); + } + + dxr3_set_property(&this->vo_driver, VO_PROP_ASPECT_RATIO, this->aspect); + return &this->vo_driver; +} + +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; +} + +static vo_frame_t *dxr3_alloc_frame(vo_driver_t *this_gen) +{ + dxr3_frame_t *frame; + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + + frame = (dxr3_frame_t *)malloc(sizeof(dxr3_frame_t)); + memset(frame, 0, sizeof(dxr3_frame_t)); + + pthread_mutex_init(&frame->vo_frame.mutex, NULL); + + if (this->enc && this->enc->on_frame_copy) + frame->vo_frame.copy = dxr3_frame_copy; + else + frame->vo_frame.copy = 0; + frame->vo_frame.field = dxr3_frame_field; + frame->vo_frame.dispose = dxr3_frame_dispose; + frame->vo_frame.driver = this_gen; + + return &frame->vo_frame; +} + +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); +} + +static void dxr3_frame_field(vo_frame_t *vo_img, int which_field) +{ + /* dummy function */ +} + +static void dxr3_frame_dispose(vo_frame_t *frame_gen) +{ + dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; + + if (frame->mem) free(frame->mem); + pthread_mutex_destroy(&frame_gen->mutex); + free(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 i; + int aspect, oheight; + + /* update the overlay window co-ords if required */ + dxr3_overlay_update(this); + + if (format == IMGFMT_MPEG) { /* talking to dxr3 decoder */ + /* 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_iheight = height; + this->video_oheight = height; + this->top_bar = 0; + this->video_aspect = ratio_code; + + frame->width = width; + frame->iheight = height; + frame->oheight = height; + + 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->aspect != aspect) + dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, aspect); + + return; + } + + /* the following is for the mpeg encoding part only */ + + aspect = this->aspect; + oheight = this->video_oheight; + + 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; + } + + if (this->add_bars == 0) { + /* don't add black bars; assume source is in 4:3 */ + ratio_code = XINE_ASPECT_RATIO_4_3; + } + + if ((this->video_width != width) || (this->video_iheight != height) || + (this->video_aspect != ratio_code)) { + /* check aspect ratio, see if we need to add black borders */ + switch (ratio_code) { + case XINE_ASPECT_RATIO_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; + + /* Tell the viewers about the aspect ratio stuff. */ + if (oheight - height > 0) + printf("video_out_dxr3: adding %d black lines to get %s aspect ratio.\n", + oheight - height, aspect == ASPECT_FULL ? "4:3" : "16:9"); + + this->video_width = width; + this->video_iheight = height; + this->video_oheight = oheight; + this->video_aspect = ratio_code; + this->format = format; + this->need_redraw = 1; + this->need_update = 1; + + if (!this->enc) { + /* no encoder plugin! Let's bug the user! */ + printf("video_out_dxr3: ********************************************************\n" + "video_out_dxr3: * *\n" + "video_out_dxr3: * need an mpeg encoder to play non-mpeg videos on dxr3 *\n" + "video_out_dxr3: * read the README.dxr3 for details. *\n" + "video_out_dxr3: * (if you get this message while trying to play an *\n" + "video_out_dxr3: * mpeg video, there is something wrong with the dxr3 *\n" + "video_out_dxr3: * decoder plugin. check if it is set up correctly) *\n" + "video_out_dxr3: * *\n" + "video_out_dxr3: ********************************************************\n"); + } + } + + /* if dimensions changed, we need to re-allocate frame memory */ + if ((frame->width != width) || (frame->iheight != height) || + (frame->oheight != oheight)) { + if (frame->mem) { + free (frame->mem); + frame->mem = NULL; + } + + /* make top black bar multiple of 16, + * so old and new macroblocks overlap */ + this->top_bar = ((oheight - height) / 32) * 16; + if (format == IMGFMT_YUY2) { + int image_size = width * oheight; /* includes black bars */ + + /* planar format, only base[0] */ + /* add one extra line for field swap stuff */ + frame->real_base[0] = xine_xmalloc_aligned(16, (image_size + width) * 2, + (void**)&frame->mem); + + /* don't use first line */ + frame->real_base[0] += width * 2; + frame->real_base[1] = frame->real_base[2] = 0; + + /* fix offset, so the decoder does not see the top black bar */ + frame->vo_frame.base[0] = frame->real_base[0] + width * 2 * this->top_bar; + frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0; + + /* 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) /* Y */ + *(frame->real_base[0] + i) = 16; + + } else { /* IMGFMT_YV12 */ + int image_size = width * oheight; /* includes black bars */ + + /* add one extra line for field swap stuff */ + frame->real_base[0] = xine_xmalloc_aligned(16, (image_size + width) * 3/2, + (void**)&frame->mem); + + /* don't use first line */ + frame->real_base[0] += width; + frame->real_base[1] = frame->real_base[0] + image_size; + frame->real_base[2] = frame->real_base[1] + 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 * this->top_bar; + frame->vo_frame.base[1] = frame->real_base[1] + width * this->top_bar/4; + frame->vo_frame.base[2] = frame->real_base[2] + width * this->top_bar/4; + + /* 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); + } + } + + 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; + } + } + + frame->width = width; + frame->iheight = height; + frame->oheight = oheight; + frame->swap_fields = this->swap_fields; + + if(this->aspect != aspect) + dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, aspect); +} + +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->iheight); + else + blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->iheight); + } + } +} + +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; + + if (frame_gen->format != IMGFMT_MPEG && this->enc && this->enc->on_display_frame) { + if (this->need_update) { + /* we cannot do this earlier, because vo_frame.duration is only valid here */ + if (this->enc && this->enc->on_update_format) + this->enc->on_update_format(this, frame); + this->need_update = 0; + } + /* for non-mpeg, the encoder plugin is responsible for calling + * frame_gen->displayed(frame_gen) ! */ + this->enc->on_display_frame(this, frame); + } else { + frame_gen->displayed(frame_gen); + } +} + +static int dxr3_redraw_needed(vo_driver_t *this_gen) +{ + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + + dxr3_overlay_update(this); + + if (this->need_redraw) { + this->need_redraw = 0; + return 1; + } + return 0; +} + +static int dxr3_get_property(vo_driver_t *this_gen, int property) +{ + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + + switch (property) { + case VO_PROP_SATURATION: + return this->bcs.saturation; + case VO_PROP_CONTRAST: + return this->bcs.contrast; + case VO_PROP_BRIGHTNESS: + return this->bcs.brightness; + case VO_PROP_ASPECT_RATIO: + return this->aspect; + case VO_PROP_COLORKEY: + return this->overlay.colorkey; + case VO_PROP_ZOOM_FACTOR: + case VO_PROP_TVMODE: + return 0; + case VO_PROP_VO_TYPE: + return VO_TYPE_DXR3; + } + printf("video_out_dxr3: property %d not implemented.\n", property); + return 0; +} + +static 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; + double ratio; + + 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 increments the value, so we make + * just a two value "loop" */ + if (value > ASPECT_FULL) value = ASPECT_ANAMORPHIC; + this->aspect = value; + fullscreen = this->overlay_enabled ? is_fullscreen(this) : 0; + + if (value == ASPECT_ANAMORPHIC) { +#if LOG_VID + printf("video_out_dxr3: setting aspect ratio to anamorphic\n"); +#endif + if (!this->overlay_enabled || fullscreen) + val = EM8300_ASPECTRATIO_16_9; + else /* The overlay window can adapt to the ratio */ + val = EM8300_ASPECTRATIO_4_3; + ratio = 16.0/9.0; + } else { +#if LOG_VID + printf("video_out_dxr3: setting aspect ratio to full\n"); +#endif + val = EM8300_ASPECTRATIO_4_3; + ratio = 4.0/3.0; + } + + if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val)) + printf("video_out_dxr3: failed to set aspect ratio (%s)\n", strerror(errno)); + + if (this->overlay_enabled && !fullscreen) { + int dummy; + this->frame_output_cb(this->user_data, this->width, this->width / ratio, + &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); + } + break; + case VO_PROP_COLORKEY: + printf("video_out_dxr3: VO_PROP_COLORKEY not implemented!"); + this->overlay.colorkey = value; + break; + case VO_PROP_ZOOM_FACTOR: + if(!this->overlay_enabled) { /* TV-out only */ + if (value == 1) { +#if LOG_VID + printf("video_out_dxr3: enabling 16:9 zoom\n"); +#endif + val = EM8300_ASPECTRATIO_4_3; + if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val)) + printf("video_out_dxr3: failed to set aspect ratio (%s)\n", strerror(errno)); + dxr3_zoomTV(this); + } else if (value == -1) { +#if LOG_VID + printf("video_out_dxr3: disabling 16:9 zoom\n"); +#endif + if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &this->aspect)) + printf("video_out_dxr3: failed to set aspect ratio (%s)\n", strerror(errno)); + } + } + break; + case VO_PROP_TVMODE: + if (++this->tv_mode > EM8300_VIDEOMODE_LAST) this->tv_mode = EM8300_VIDEOMODE_PAL; +#if LOG_VID + printf("video_out_dxr3: Changing TVMode to "); +#endif + if (this->tv_mode == EM8300_VIDEOMODE_PAL) printf("PAL\n"); + if (this->tv_mode == EM8300_VIDEOMODE_PAL60) printf("PAL60\n"); + if (this->tv_mode == EM8300_VIDEOMODE_NTSC) printf("NTSC\n"); + if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode)) + printf("video_out_dxr3: setting video mode failed (%s)\n", strerror(errno)); + break; + } + + if (bcs_changed) { + if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs)) + printf("video_out_dxr3: 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; +} + +static void dxr3_get_property_min_max(vo_driver_t *this_gen, int property, + int *min, int *max) +{ + 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 int dxr3_gui_data_exchange(vo_driver_t *this_gen, int data_type, void *data) +{ + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + + if (!this->overlay_enabled && !this->tv_switchable) return 0; + + switch (data_type) { + 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(this_gen, VO_PROP_ASPECT_RATIO, this->aspect); + } + 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)data; + int val; + if (!window_showing) { +#if LOG_VID + printf("video_out_dxr3: Hiding video window and diverting video to TV\n"); +#endif + val = EM8300_OVERLAY_MODE_OFF; + ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &val); + this->overlay_enabled = 0; + } else { +#if LOG_VID + printf("video_out_dxr3: Using video window for overlaying video\n"); +#endif + val = EM8300_OVERLAY_MODE_OVERLAY; + ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &val); + this->overlay_enabled = 1; + } + dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, this->aspect); + } + break; + default: + return -1; + } + return 0; +} + +static void dxr3_exit(vo_driver_t *this_gen) +{ + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + int val = EM8300_OVERLAY_MODE_OFF; + +#if LOG_VID + printf("video_out_dxr3: vo exit called\n"); +#endif + if (this->enc && this->enc->on_close) + this->enc->on_close(this); + if(this->overlay_enabled) + ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &val); + + free(this); +} + + +static 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); + +#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->frame_output_cb = (void *)vis->frame_output_cb; + +#if LOG_OVR + printf("video_out_dxr3: xres: %d, yres: %d, depth: %d\n", + this->overlay.screen_xres, this->overlay.screen_yres, this->overlay.screen_depth); +#endif +} + +/* dxr3_overlay_read_state helper structure */ +#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; +}; + +/* dxr3_overlay_read_state helper function */ +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) == 0) { + *ptr = lut[i].ptr; + *type = lut[i].type; +#if LOG_OVR + printf("video_out_dxr3: found parameter \"%s\"\n", name); +#endif + return 1; + } +#if LOG_OVR + printf("video_out_dxr3: WARNING: unknown parameter \"%s\"\n", name); +#endif + return 0; +} + +static int dxr3_overlay_read_state(dxr3_overlay_t *this) +{ + char *loc; + char fname[256], tmp[128], line[256]; + FILE *fp; + struct lut_entry lut[] = { + {"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} + }; + char *tok; + void *ptr; + int type; + int j; + + /* 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"); + + snprintf(tmp, sizeof(tmp), "/res_%dx%dx%d", + this->screen_xres, this->screen_yres, this->screen_depth); + strncpy(fname, getenv("HOME"), sizeof(fname) - strlen(tmp) - sizeof("/.overlay")); + fname[sizeof(fname) - strlen(tmp) - sizeof("/.overlay")] = '\0'; + strcat(fname, "/.overlay"); + strcat(fname, tmp); +#if LOG_OVR + printf("video_out_dxr3: attempting to open %s\n", fname); +#endif + if (!(fp = fopen(fname, "r"))) { + printf("video_out_dxr3: ERROR Reading overlay init file. Run autocal!\n"); + return -1; + } + + 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 LOG_OVR + printf("video_out_dxr3: value \"%s\" = %d\n", tok, *(int *)ptr); +#endif + break; + case TYPE_XINT: + sscanf(tok, "%x", (int *)ptr); +#if LOG_OVR + printf("video_out_dxr3: value \"%s\" = %d\n", tok, *(int *)ptr); +#endif + break; + case TYPE_FLOAT: + sscanf(tok, "%f", (float *)ptr); +#if LOG_OVR + printf("video_out_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); +#if LOG_OVR + printf("video_out_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); +#if LOG_OVR + printf("video_out_dxr3: value (%d,m) \"%s\" = %f\n", j, tok, ((struct coeff *)ptr)[j].m); +#endif + tok = strtok(NULL, " \n"); + } + break; + } + } + } + + fclose(fp); + /* restore original locale */ + setlocale(LC_NUMERIC, loc); + + return 0; +} + +/* dxr3_overlay_set_keycolor helper function */ +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; +} + +static int dxr3_overlay_set_keycolor(dxr3_overlay_t *this) +{ + 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; + int32_t overlay_limit; + int ret; + +#if LOG_OVR + printf("video_out_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]); +#if LOG_OVR + printf("video_out_dxr3: lower overlay_limit = %d\n", overlay_limit); +#endif + attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_LOWER; + attr.value = overlay_limit; + if ((ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)) < 0) { + printf("video_out_dxr3: WARNING: error setting overlay lower 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 LOG_OVR + printf("video_out_dxr3: upper overlay_limit = %d\n", overlay_limit); +#endif + attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_UPPER; + attr.value = overlay_limit; + if ((ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)) < 0) + printf("video_out_dxr3: WARNING: error setting overlay upper limit attribute\n"); + return ret; +} + +static 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); +} + + +static 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); +} + +static 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, + this->video_width, this->video_oheight, + &gxpos, &gypos, &gw, &gh, &gui_win_x, &gui_win_y); + + if (this->xpos != gxpos || this->ypos != gypos || + this->width != gw || this->height != gh) { + XWindowAttributes a; + Window junkwin; + int rx, ry; + + /* detect true window position and adapt overlay to it */ + XLockDisplay(this->display); + XSetForeground(this->display, this->gc, this->color.pixel); + XGetWindowAttributes(this->display, this->win, &a); + XTranslateCoordinates (this->display, this->win, a.root, + gxpos + 1, gypos + 1, &rx, &ry, &junkwin); + XUnlockDisplay(this->display); + + this->xpos = rx; + this->ypos = ry; + this->width = gw; + this->height = gh; + + dxr3_overlay_set_window(&this->overlay, this->xpos, this->ypos, + this->width, this->height); + } + } +} + +static void dxr3_zoomTV(dxr3_driver_t *this) +{ + em8300_register_t frame, visible, update; + + /* change left bound */ + frame.microcode_register = 1; + frame.reg = 93; // dicom frame left + frame.val = 0x10; + + visible.microcode_register = 1; + visible.reg = 97; // dicom visible left + visible.val = 0x10; + + update.microcode_register = 1; + update.reg = 65; // dicom_update + update.val = 1; + + 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 bound */ + frame.microcode_register = 1; + frame.reg = 94; // dicom frame right + frame.val = 0x10; + + visible.microcode_register = 1; + visible.reg = 98; // dicom visible right + visible.val = 968; + + update.microcode_register = 1; + update.reg = 65; // dicom_update + update.val = 1; + + ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame); + ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible); + ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update); +} + +static void dxr3_translate_gui2video(dxr3_driver_t *this, int x, int y, + int *vid_x, int *vid_y) +{ + *vid_x = x * this->video_width / this->width; + *vid_y = y * this->video_oheight / this->height - this->top_bar; +} + +static int is_fullscreen(dxr3_driver_t *this) +{ + XWindowAttributes a; + + XGetWindowAttributes(this->display, this->win, &a); + + return + a.x == 0 && + a.y == 0 && + a.width == this->overlay.screen_xres && + a.height == this->overlay.screen_yres; +} + + +static 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("video_out_dxr3: setting add_bars to correct aspect ratio to %s\n", + (this->add_bars ? "on" : "off")); +} + +static 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("video_out_dxr3: setting swap fields to %s\n", + (this->swap_fields ? "on" : "off")); +} + +static void dxr3_update_enhanced_mode(void *data, cfg_entry_t *entry) +{ + dxr3_driver_t *this = (dxr3_driver_t *)data; + this->enhanced_mode = entry->num_value; + printf("video_out_dxr3: setting enhanced encoding playback to %s\n", + (this->enhanced_mode ? "on" : "off")); +} diff --git a/src/dxr3/video_out_dxr3.h b/src/dxr3/video_out_dxr3.h new file mode 100644 index 000000000..3f8be66f5 --- /dev/null +++ b/src/dxr3/video_out_dxr3.h @@ -0,0 +1,132 @@ +/* + * 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: video_out_dxr3.h,v 1.1 2002/05/24 22:09:44 miguelfreitas Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <X11/Xlib.h> + +#include "xine_internal.h" +#include "dxr3.h" + +/* values for fd_video indicating why it is closed */ +#define CLOSED_FOR_DECODER -1 +#define CLOSED_FOR_ENCODER -2 + + +/* plugin structures */ +typedef struct encoder_data_s encoder_data_t; + +typedef enum { ENC_FAME, ENC_RTE } encoder_type; + + +struct coeff { + float k,m; +}; + +typedef struct dxr3_overlay_s { + 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 struct dxr3_driver_s { + vo_driver_t vo_driver; + config_values_t *config; + + char devname[128]; + char devnum[3]; + int fd_control; + int fd_video; /* to access the relevant dxr3 devices */ + + int enhanced_mode; + int swap_fields; /* swap fields */ + int add_bars; /* add black bars to correct a.r. */ + + int aspect; + int tv_mode; + int overlay_enabled; + int tv_switchable; /* can switch from overlay<->tvout */ + em8300_bcs_t bcs; + + encoder_data_t *enc; /* encoder data */ + int format; /* color format */ + int video_iheight; /* input height (before adding black bars) */ + int video_oheight; /* output height (after adding bars) */ + int video_width; + int video_aspect; + int top_bar; /* the height of the upper black bar */ + int need_redraw; /* the image on screen needs redrawing */ + int need_update; /* the mpeg encoder needs to be updated */ + + dxr3_overlay_t overlay; + Display *display; + Drawable win; + GC gc; + XColor color; + int xpos, ypos; + int width, height; + + 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_y); +} dxr3_driver_t; + +typedef struct dxr3_frame_s { + vo_frame_t vo_frame; + int width, iheight, oheight; + uint8_t *mem; /* allocated for YV12 or YUY2 buffers */ + uint8_t *real_base[3]; /* yuv/yuy2 buffers in mem aligned on 16 */ + 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 *, dxr3_frame_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 plugins initialization functions */ +#ifdef HAVE_LIBRTE +int dxr3_rte_init(dxr3_driver_t *); +#endif +#ifdef HAVE_LIBFAME +int dxr3_fame_init(dxr3_driver_t *); +#endif diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 4a137b2df..8ad6d46ec 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_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: audio_decoder.c,v 1.72 2002/04/29 23:32:00 jcdutton Exp $ + * $Id: audio_decoder.c,v 1.73 2002/05/24 22:09:44 miguelfreitas Exp $ * * * functions that implement audio decoding @@ -266,7 +266,14 @@ void audio_decoder_init (xine_t *this) { return; } - this->audio_fifo = fifo_buffer_new (50, 8192); + /* The fifo size is based on dvd playback where buffers are filled + * with 2k of data. With 230 buffers and a typical audio data rate + * of 1.8 Mbit/s (four ac3 streams), the fifo can hold about 2 seconds + * of audio, wich should be enough to compensate for drive delays. + * We provide buffers of 8k size instead of 2k for demuxers sending + * larger chunks. + */ + this->audio_fifo = fifo_buffer_new (230, 8192); this->audio_channel_user = -1; this->audio_channel_auto = 0; this->audio_type = 0; diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 31cff4704..3915e37bd 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_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: video_decoder.c,v 1.84 2002/04/29 23:32:00 jcdutton Exp $ + * $Id: video_decoder.c,v 1.85 2002/05/24 22:09:45 miguelfreitas Exp $ * */ @@ -282,6 +282,13 @@ void video_decoder_init (xine_t *this) { struct sched_param pth_params; int err; + /* The fifo size is based on dvd playback where buffers are filled + * with 2k of data. With 500 buffers and a typical video data rate + * of 4 Mbit/s, the fifo can hold about 2 seconds of video, wich + * should be enough to compensate for drive delays. + * We provide buffers of 8k size instead of 2k for demuxers sending + * larger chunks. + */ this->video_fifo = fifo_buffer_new (500, 8192); pthread_attr_init(&pth_attrs); |