diff options
author | Michael Roitzsch <mroi@users.sourceforge.net> | 2002-10-26 14:35:04 +0000 |
---|---|---|
committer | Michael Roitzsch <mroi@users.sourceforge.net> | 2002-10-26 14:35:04 +0000 |
commit | e6926fa3475e1c528aeba7a73daabfa6d70d84e5 (patch) | |
tree | 829802b044ed971210cfef79a5932ab4ad963fc1 | |
parent | 28702c7e332217caec870f664ad5423ca2547fac (diff) | |
download | xine-lib-e6926fa3475e1c528aeba7a73daabfa6d70d84e5.tar.gz xine-lib-e6926fa3475e1c528aeba7a73daabfa6d70d84e5.tar.bz2 |
- dxr3 adapted to new API (compiles, but untested)
- use vo_scale helper for video_out_dxr3 (overlay display is now
pixel aspect corrected)
- some additional dxr3 fixes, especially overlay
(menus & overlay, forgotten brightness/constrast/saturation setting ...)
CVS patchset: 3010
CVS date: 2002/10/26 14:35:04
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/dxr3/dxr3.h | 6 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_spu.c | 328 | ||||
-rw-r--r-- | src/dxr3/dxr3_decode_video.c | 351 | ||||
-rw-r--r-- | src/dxr3/dxr3_mpeg_encoders.c | 16 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.c | 13 | ||||
-rw-r--r-- | src/dxr3/dxr3_scr.h | 4 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.c | 362 | ||||
-rw-r--r-- | src/dxr3/video_out_dxr3.h | 96 |
9 files changed, 640 insertions, 537 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f34afe541..83e44da2c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ SUBDIRS = \ xine-engine \ audio_out \ video_out \ + dxr3 \ input \ demuxers \ libffmpeg \ diff --git a/src/dxr3/dxr3.h b/src/dxr3/dxr3.h index 0a2396d8b..2790a1809 100644 --- a/src/dxr3/dxr3.h +++ b/src/dxr3/dxr3.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3.h,v 1.4 2002/09/05 20:44:39 mroi Exp $ + * $Id: dxr3.h,v 1.5 2002/10/26 14:35:04 mroi Exp $ */ #ifndef HAVE_DXR3_H @@ -36,5 +36,9 @@ /* image format used by dxr3_decoder to tag undecoded mpeg data */ #define XINE_IMGFMT_DXR3 (('3'<<24)|('R'<<16)|('X'<<8)|'D') +/* name of the dxr3 video out plugin + * (used by decoders to check for dxr3 presence) */ +#define DXR3_VO_ID "dxr3" + #endif diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c index dfb4cbf3d..8c3540ac9 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.20 2002/09/27 13:07:43 mroi Exp $ + * $Id: dxr3_decode_spu.c,v 1.21 2002/10/26 14:35:04 mroi Exp $ */ /* dxr3 spu decoder plugin. @@ -52,7 +52,7 @@ #define MAX_SPU_STREAMS 32 -/* plugin initialization function */ +/* plugin class initialization function */ static void *dxr3_spudec_init_plugin(xine_t *xine, void *); @@ -71,14 +71,18 @@ plugin_info_t xine_plugin_info[] = { }; -/* functions required by xine api */ -static char *dxr3_spudec_get_id(void); -static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out); +/* plugin class functions */ +static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xine_stream_t *stream); +static char *dxr3_spudec_get_identifier(spu_decoder_class_t *class_gen); +static char *dxr3_spudec_get_description(spu_decoder_class_t *class_gen); +static void dxr3_spudec_class_dispose(spu_decoder_class_t *class_gen); + +/* plugin instance functions */ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf); -static int dxr3_spudec_get_nav_pci(spu_decoder_t *this_gen, pci_t *pci); static void dxr3_spudec_reset(spu_decoder_t *this_gen); -static void dxr3_spudec_close(spu_decoder_t *this_gen); static void dxr3_spudec_dispose(spu_decoder_t *this_gen); +static int dxr3_spudec_get_nav_pci(spu_decoder_t *this_gen, pci_t *pci); +static void dxr3_spudec_set_button(spu_decoder_t *this_gen, int32_t button, int32_t mode); /* plugin structures */ typedef struct dxr3_spu_stream_state_s { @@ -91,13 +95,22 @@ typedef struct dxr3_spu_stream_state_s { int bytes_passed; /* used to parse the spu */ } dxr3_spu_stream_state_t; +typedef struct dxr3_spudec_class_s { + spu_decoder_class_t spu_decoder_class; + + int instance; /* we allow only one instance of this plugin */ + + char devname[128]; + char devnum[3]; +} dxr3_spudec_class_t; + typedef struct dxr3_spudec_s { spu_decoder_t spu_decoder; - xine_t *xine; + dxr3_spudec_class_t *class; + xine_stream_t *stream; dxr3_driver_t *dxr3_vo; /* we need to talk to the video out */ + xine_event_queue_t *event_queue; - char devname[128]; - char devnum[3]; int fd_spu; /* to access the dxr3 spu device */ dxr3_spu_stream_state_t spu_stream_state[MAX_SPU_STREAMS]; @@ -113,21 +126,19 @@ typedef struct dxr3_spudec_s { } dxr3_spudec_t; /* helper functions */ -static int dxr3_present(xine_t *xine); -static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen); +static int dxr3_present(xine_stream_t *stream); +static void dxr3_spudec_handle_event(dxr3_spudec_t *this); static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300_button_t *btn); static void dxr3_swab_clut(int* clut); static void *dxr3_spudec_init_plugin(xine_t *xine, void* data) { - dxr3_spudec_t *this; + dxr3_spudec_class_t *this; const char *confstr; int dashpos; - if (!dxr3_present(xine)) return NULL; - - this = (dxr3_spudec_t *)malloc(sizeof(dxr3_spudec_t)); + this = (dxr3_spudec_class_t *)malloc(sizeof(dxr3_spudec_class_t)); if (!this) return NULL; confstr = xine->config->register_string(xine->config, @@ -145,56 +156,54 @@ static void *dxr3_spudec_init_plugin(xine_t *xine, void* data) this->devnum[0] = '\0'; } - this->spu_decoder.get_identifier = dxr3_spudec_get_id; - this->spu_decoder.init = dxr3_spudec_init; - this->spu_decoder.decode_data = dxr3_spudec_decode_data; - this->spu_decoder.get_nav_pci = dxr3_spudec_get_nav_pci; - this->spu_decoder.reset = dxr3_spudec_reset; - this->spu_decoder.close = dxr3_spudec_close; - this->spu_decoder.dispose = dxr3_spudec_dispose; + this->spu_decoder_class.open_plugin = dxr3_spudec_open_plugin; + this->spu_decoder_class.get_identifier = dxr3_spudec_get_identifier; + this->spu_decoder_class.get_description = dxr3_spudec_get_description; + this->spu_decoder_class.dispose = dxr3_spudec_class_dispose; - this->xine = xine; - /* We need to talk to dxr3 video out to coordinate spus and overlays */ - this->dxr3_vo = (dxr3_driver_t *)xine->video_driver; - - this->fd_spu = 0; - this->menu = 0; - this->button_filter = 1; - this->pci.hli.hl_gi.hli_ss = 0; - this->buttonN = 1; - - this->aspect = XINE_VO_ASPECT_4_3; + this->instance = 0; - pthread_mutex_init(&this->pci_lock, NULL); - - xine_register_event_listener(xine, dxr3_spudec_event_listener, this); - - return &this->spu_decoder; + return &this->spu_decoder_class; } -static char *dxr3_spudec_get_id(void) -{ - return "dxr3-spudec"; -} -static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out) +static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xine_stream_t *stream) { - dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; + dxr3_spudec_t *this; + dxr3_spudec_class_t *class = (dxr3_spudec_class_t *)class_gen; char tmpstr[128]; int i; - pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); + if (class->instance) return NULL; + if (!dxr3_present(stream)) return NULL; + + this = (dxr3_spudec_t *)malloc(sizeof(dxr3_spudec_t)); + if (!this) return NULL; + this->spu_decoder.decode_data = dxr3_spudec_decode_data; + this->spu_decoder.reset = dxr3_spudec_reset; + this->spu_decoder.dispose = dxr3_spudec_dispose; + this->spu_decoder.get_nav_pci = dxr3_spudec_get_nav_pci; + this->spu_decoder.set_button = dxr3_spudec_set_button; + + this->class = class; + this->stream = stream; + /* We need to talk to dxr3 video out to coordinate spus and overlays */ + this->dxr3_vo = (dxr3_driver_t *)stream->video_driver; + this->event_queue = xine_event_new_queue(stream); + + pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (this->dxr3_vo->fd_spu) this->fd_spu = this->dxr3_vo->fd_spu; else { /* open dxr3 spu device */ - snprintf(tmpstr, sizeof(tmpstr), "%s_sp%s", this->devname, this->devnum); + snprintf(tmpstr, sizeof(tmpstr), "%s_sp%s", class->devname, class->devnum); if ((this->fd_spu = open(tmpstr, O_WRONLY)) < 0) { printf("dxr3_decode_spu: Failed to open spu device %s (%s)\n", tmpstr, strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - return; + free(this); + return NULL; } #if LOG_SPU printf ("dxr3_decode_spu: init: SPU_FD = %i\n",this->fd_spu); @@ -203,22 +212,52 @@ static void dxr3_spudec_init(spu_decoder_t *this_gen, vo_instance_t *vo_out) * access to the same spu device */ this->dxr3_vo->fd_spu = this->fd_spu; } - pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - for (i=0; i < MAX_SPU_STREAMS; i++) { + for (i = 0; i < MAX_SPU_STREAMS; i++) { this->spu_stream_state[i].stream_filter = 1; this->spu_stream_state[i].spu_length = 0; } + + this->menu = 0; + this->button_filter = 1; + this->pci.hli.hl_gi.hli_ss = 0; + this->buttonN = 1; + + this->aspect = XINE_VO_ASPECT_4_3; + + pthread_mutex_init(&this->pci_lock, NULL); + + class->instance = 1; + + return &this->spu_decoder; +} + +static char *dxr3_spudec_get_identifier(spu_decoder_class_t *class_gen) +{ + return "dxr3-spudec"; +} + +static char *dxr3_spudec_get_description(spu_decoder_class_t *class_gen) +{ + return "subtitle decoder plugin using the hardware decoding capabilities of a DXR3 decoder card"; } +static void dxr3_spudec_class_dispose(spu_decoder_class_t *class_gen) +{ + free(class_gen); +} + + static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; ssize_t written; uint32_t stream_id = buf->type & 0x1f; dxr3_spu_stream_state_t *state = &this->spu_stream_state[stream_id]; - uint32_t spu_channel = this->xine->spu_channel; + uint32_t spu_channel = this->stream->spu_channel; + + dxr3_spudec_handle_event(this); if (buf->type == BUF_SPU_CLUT) { #if LOG_SPU @@ -270,12 +309,14 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) if ( this->pci.hli.hl_gi.fosl_btnn > 0) { /* a button is forced here, inform nav plugin */ spu_button_t spu_button; - xine_spu_event_t spu_event; - this->buttonN = this->pci.hli.hl_gi.fosl_btnn ; - spu_event.event.type = XINE_EVENT_INPUT_BUTTON_FORCE; - spu_event.data = &spu_button; - spu_button.buttonN = this->buttonN; - xine_send_event(this->xine, &spu_event.event); + xine_event_t event; + this->buttonN = this->pci.hli.hl_gi.fosl_btnn ; + event.type = XINE_EVENT_INPUT_BUTTON_FORCE; + event.stream = this->stream; + event.data = &spu_button; + event.data_length = sizeof(spu_button); + spu_button.buttonN = this->buttonN; + xine_event_send(this->stream, &event); } if ((dxr3_spudec_copy_nav_to_btn(this, 0, &btn ) > 0)) { pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); @@ -361,12 +402,10 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) #endif return; } - if (this->aspect == XINE_VO_ASPECT_ANAMORPHIC && - this->xine->spu_channel_user == -1 && this->xine->spu_channel_letterbox >= 0 && - this->xine->video_driver->get_property(this->xine->video_driver, VO_PROP_VO_TYPE) == - VO_TYPE_DXR3_LETTERBOXED) { - /* Use the letterbox version of the subpicture for tv out. */ - spu_channel = this->xine->spu_channel_letterbox; + if (this->aspect == XINE_VO_ASPECT_ANAMORPHIC && !this->dxr3_vo->widescreen_enabled && + this->stream->spu_channel_user == -1 && this->stream->spu_channel_letterbox >= 0) { + /* Use the letterbox version of the subpicture for letterboxed display. */ + spu_channel = this->stream->spu_channel_letterbox; } if ((spu_channel & 0x1f) != stream_id) { #if LOG_SPU @@ -388,10 +427,9 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) int64_t vpts; uint32_t vpts32; - vpts = this->xine->metronom->got_spu_packet( - this->xine->metronom, buf->pts); + vpts = this->stream->metronom->got_spu_packet(this->stream->metronom, buf->pts); /* estimate with current time, when metronom doesn't know */ - if (!vpts) vpts = this->xine->metronom->get_current_time(this->xine->metronom); + if (!vpts) vpts = this->stream->metronom->get_current_time(this->stream->metronom); #if LOG_PTS printf("dxr3_decode_spu: pts = %lld vpts = %lld\n", buf->pts, vpts); #endif @@ -425,16 +463,6 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); } -static int dxr3_spudec_get_nav_pci(spu_decoder_t *this_gen, pci_t *pci) -{ - dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - - pthread_mutex_lock(&this->pci_lock); - memcpy(pci, &this->pci, sizeof(pci_t) ); - pthread_mutex_unlock(&this->pci_lock); - return 1; -} - static void dxr3_spudec_reset(spu_decoder_t *this_gen) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; @@ -444,9 +472,10 @@ static void dxr3_spudec_reset(spu_decoder_t *this_gen) this->spu_stream_state[i].spu_length = 0; } -static void dxr3_spudec_close(spu_decoder_t *this_gen) +static void dxr3_spudec_dispose(spu_decoder_t *this_gen) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; + #if LOG_SPU printf("dxr3_decode_spu: close: SPU_FD = %i\n",this->fd_spu); #endif @@ -455,95 +484,90 @@ static void dxr3_spudec_close(spu_decoder_t *this_gen) this->fd_spu = 0; this->dxr3_vo->fd_spu = 0; pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); -} - -static void dxr3_spudec_dispose(spu_decoder_t *this_gen) -{ - dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - xine_remove_event_listener(this->xine, dxr3_spudec_event_listener); + xine_event_dispose_queue(this->event_queue); pthread_mutex_destroy(&this->pci_lock); + this->class->instance = 0; free (this); } - -static int dxr3_present(xine_t *xine) +static int dxr3_spudec_get_nav_pci(spu_decoder_t *this_gen, pci_t *pci) { - int info; + dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - if (xine && xine->video_driver) { - info = xine->video_driver->get_property(xine->video_driver, VO_PROP_VO_TYPE); -#ifdef LOG_SPU - printf("dxr3_decode_spu: dxr3 presence test: info = %d\n", info); -#endif - if ((info != VO_TYPE_DXR3_LETTERBOXED) && (info != VO_TYPE_DXR3_WIDE)) - return 0; - } + pthread_mutex_lock(&this->pci_lock); + memcpy(pci, &this->pci, sizeof(pci_t) ); + pthread_mutex_unlock(&this->pci_lock); return 1; } -static void dxr3_spudec_event_listener(void *this_gen, xine_event_t *event_gen) +static void dxr3_spudec_set_button(spu_decoder_t *this_gen, int32_t button, int32_t mode) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - xine_spu_event_t *event = (xine_spu_event_t *)event_gen; + em8300_button_t btn; -#if LOG_SPU - printf("dxr3_decode_spu: event caught: SPU_FD = %i\n",this->fd_spu); -#endif - - switch (event->event.type) { - case XINE_EVENT_SPU_BUTTON: - { - spu_button_t *but = event->data; - em8300_button_t btn; #if LOG_BTN - printf("dxr3_decode_spu: got SPU_BUTTON\n"); + printf("dxr3_decode_spu: setting button\n"); #endif - pthread_mutex_lock(&this->pci_lock); - this->buttonN = but->buttonN; - if ((but->show > 0) && !this->button_filter && - (dxr3_spudec_copy_nav_to_btn(this, but->show - 1, &btn) > 0)) { - pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) - printf("dxr3_decode_spu: failed to set spu button (%s)\n", - strerror(errno)); - pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - } - pthread_mutex_unlock(&this->pci_lock); - if (but->show == 2) this->button_filter = 1; + this->buttonN = button; + pthread_mutex_lock(&this->pci_lock); + if (mode > 0 && !this->button_filter && + (dxr3_spudec_copy_nav_to_btn(this, mode - 1, &btn ) > 0)) { + pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); + if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) + printf("dxr3_decode_spu: failed to set spu button (%s)\n", + strerror(errno)); + pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); + } + pthread_mutex_unlock(&this->pci_lock); + if (mode == 2) this->button_filter = 1; #if LOG_BTN - printf("dxr3_decode_spu: buttonN = %u\n",but->buttonN); + printf("dxr3_decode_spu: buttonN = %u\n", this->buttonN); #endif +} + + +static int dxr3_present(xine_stream_t *stream) +{ + plugin_node_t *node; + video_driver_class_t *vo_class; + int present = 0; + + if (stream->video_driver && stream->video_driver->node) { + node = (plugin_node_t *)stream->video_driver->node; + if (node->plugin_class) { + vo_class = (video_driver_class_t *)node->plugin_class; + if (vo_class->get_identifier) + present = (strcmp(vo_class->get_identifier(vo_class), DXR3_VO_ID) == 0); } - break; - - case XINE_EVENT_SPU_CLUT: - { - spudec_clut_table_t *clut = event->data; -#if LOG_SPU - printf("dxr3_decode_spu: got SPU_CLUT\n"); + } +#ifdef LOG_SPU + printf("dxr3_decode_video: dxr3 %s\n", present ? "present" : "not present"); #endif -#ifdef WORDS_BIGENDIAN - dxr3_swab_clut(clut->clut); + return present; +} + +static void dxr3_spudec_handle_event(dxr3_spudec_t *this) +{ + xine_event_t *event; + + if (!(event = xine_event_get(this->event_queue))) return; + +#if LOG_SPU + printf("dxr3_decode_spu: event caught: SPU_FD = %i\n",this->fd_spu); #endif - pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); - if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, clut->clut)) - printf("dxr3_decode_spu: failed to set CLUT (%s)\n", - strerror(errno)); - /* remember clut, when video out places some overlay we may need to restore it */ - memcpy(this->clut, clut->clut, 16 * sizeof(uint32_t)); - this->dxr3_vo->clut_cluttered = 0; - pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - } - break; - case XINE_EVENT_FRAME_CHANGE: - this->height = ((xine_frame_change_event_t *)event)->height; - this->aspect = ((xine_frame_change_event_t *)event)->aspect; + + switch (event->type) { + case XINE_EVENT_FRAME_FORMAT_CHANGE: + this->height = ((xine_format_change_data_t *)event->data)->height; + this->aspect = ((xine_format_change_data_t *)event->data)->aspect; #if LOG_BTN printf("dxr3_decode_spu: aspect changed to %d\n", this->aspect); #endif break; } + + xine_event_free(event); } static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300_button_t *btn) @@ -552,16 +576,18 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 if ((this->buttonN <= 0) || (this->buttonN > this->pci.hli.hl_gi.btn_ns)) { spu_button_t spu_button; - xine_spu_event_t spu_event; + xine_event_t event; printf("dxr3_decode_spu: Unable to select button number %i as it doesn't exist. Forcing button 1\n", this->buttonN); - this->buttonN = 1; + this->buttonN = 1; /* inform nav plugin that we have chosen another button */ - spu_event.event.type = XINE_EVENT_INPUT_BUTTON_FORCE; - spu_event.data = &spu_button; - spu_button.buttonN = this->buttonN; - xine_send_event(this->xine, &spu_event.event); + event.type = XINE_EVENT_INPUT_BUTTON_FORCE; + event.stream = this->stream; + event.data = &spu_button; + event.data_length = sizeof(spu_button); + spu_button.buttonN = this->buttonN; + xine_event_send(this->stream, &event); } button_ptr = &this->pci.hli.btnit[this->buttonN - 1]; @@ -577,10 +603,10 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 btn->right = button_ptr->x_end; btn->bottom = button_ptr->y_end; if (this->aspect == XINE_VO_ASPECT_ANAMORPHIC && - this->xine->video_driver->get_property(this->xine->video_driver, VO_PROP_VO_TYPE) == - VO_TYPE_DXR3_LETTERBOXED && this->xine->spu_channel_user == -1 && - this->xine->spu_channel_letterbox != this->xine->spu_channel && - this->xine->spu_channel_letterbox >= 0) { + !this->dxr3_vo->widescreen_enabled && + this->stream->spu_channel_user == -1 && + this->stream->spu_channel_letterbox != this->stream->spu_channel && + this->stream->spu_channel_letterbox >= 0) { /* modify button areas for letterboxed anamorphic menus on tv out */ int top_black_bar = this->height / 8; btn->top = btn->top * 3 / 4 + top_black_bar; diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c index b6a037f75..f1c69dc3d 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.16 2002/09/18 15:43:34 mroi Exp $ + * $Id: dxr3_decode_video.c,v 1.17 2002/10/26 14:35:04 mroi Exp $ */ /* dxr3 video decoder plugin. @@ -38,6 +38,7 @@ #include "xine_internal.h" #include "buffer.h" #include "dxr3_scr.h" +#include "video_out_dxr3.h" #include "dxr3.h" #define LOG_VID 1 @@ -57,7 +58,7 @@ #define HEADER_OFFSET 0 -/* plugin initialization function */ +/* plugin class initialization function */ static void *dxr3_init_plugin(xine_t *xine, void *); @@ -76,55 +77,65 @@ plugin_info_t xine_plugin_info[] = { }; -/* functions required by xine api */ -static char *dxr3_get_id(void); -static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out); -static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf); -static void dxr3_flush(video_decoder_t *this_gen); -static void dxr3_reset(video_decoder_t *this_gen); -static void dxr3_close(video_decoder_t *this_gen); -static void dxr3_dispose(video_decoder_t *this_gen); +/* plugin class functions */ +static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream); +static char *dxr3_get_identifier(video_decoder_class_t *class_gen); +static char *dxr3_get_description(video_decoder_class_t *class_gen); +static void dxr3_class_dispose(video_decoder_class_t *class_gen); -/* plugin structure */ -typedef struct dxr3_decoder_s { - video_decoder_t video_decoder; - vo_instance_t *video_out; - dxr3_scr_t *scr; - xine_t *xine; - - char devname[128]; - char devnum[3]; - int fd_control; - int fd_video; /* to access the dxr3 devices */ - - int have_header_info; - int width; - int height; - int aspect; - int frame_rate_code; - int repeat_first_field; /* mpeg stream header data */ - - int force_aspect; /* when input plugin has better info, we are forced - * to use a certain aspect */ - int last_width; - int last_height; - int last_aspect; /* used to detect changes for event sending */ - - int sync_every_frame; - int sync_retry; - int enhanced_mode; - int resync_window; - int skip_count; /* syncing parameters */ - - int correct_durations; - int64_t last_vpts; - int force_duration_window; - int avg_duration; /* logic to correct broken frame rates */ +/* plugin instance functions */ +static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf); +static void dxr3_reset(video_decoder_t *this_gen); +static void dxr3_flush(video_decoder_t *this_gen); +static void dxr3_dispose(video_decoder_t *this_gen); + +/* plugin structures */ +typedef struct dxr3_decoder_class_s { + video_decoder_class_t video_decoder_class; + + int instance; /* we allow only one instance of this plugin */ + char devname[128]; + char devnum[3]; +} dxr3_decoder_class_t; + +typedef struct dxr3_decoder_s { + video_decoder_t video_decoder; + dxr3_decoder_class_t *class; + xine_stream_t *stream; + dxr3_scr_t *scr; + dxr3_driver_t *dxr3_vo; /* we need to talk to the dxr3 video out */ + + int fd_control; + int fd_video; /* to access the dxr3 devices */ + + int have_header_info; + int width; + int height; + int aspect; + int frame_rate_code; + int repeat_first_field; /* mpeg stream header data */ + + int force_aspect; /* when input plugin has better info, we are forced + * to use a certain aspect */ + int last_width; + int last_height; + int last_aspect; /* used to detect changes for event sending */ + + int sync_every_frame; + int sync_retry; + int enhanced_mode; + int resync_window; + int skip_count; /* syncing parameters */ + + int correct_durations; + int64_t last_vpts; + int force_duration_window; + int avg_duration; /* logic to correct broken frame rates */ } dxr3_decoder_t; /* helper functions */ -static int dxr3_present(xine_t *xine); +static int dxr3_present(xine_stream_t *stream); 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(dxr3_decoder_t *this); @@ -137,15 +148,12 @@ static void dxr3_update_correct_durations(void *this_gen, xine_cfg_entry_t static void *dxr3_init_plugin(xine_t *xine, void *data) { - dxr3_decoder_t *this; + dxr3_decoder_class_t *this; config_values_t *cfg; const char *confstr; int dashpos; - int64_t cur_offset; - - if (!dxr3_present(xine)) return NULL; - this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t)); + this = (dxr3_decoder_class_t *)malloc(sizeof (dxr3_decoder_class_t)); if (!this) return NULL; cfg = xine->config; @@ -163,49 +171,44 @@ static void *dxr3_init_plugin(xine_t *xine, void *data) this->devnum[0] = '\0'; } - this->video_decoder.get_identifier = dxr3_get_id; - this->video_decoder.init = dxr3_init; - this->video_decoder.decode_data = dxr3_decode_data; - this->video_decoder.flush = dxr3_flush; - this->video_decoder.reset = dxr3_reset; - this->video_decoder.close = dxr3_close; - this->video_decoder.dispose = dxr3_dispose; + this->video_decoder_class.open_plugin = dxr3_open_plugin; + this->video_decoder_class.get_identifier = dxr3_get_identifier; + this->video_decoder_class.get_description = dxr3_get_description; + this->video_decoder_class.dispose = dxr3_class_dispose; - this->scr = NULL; - this->xine = xine; + this->instance = 0; - this->sync_every_frame = cfg->register_bool(cfg, - "dxr3.sync_every_frame", 0, _("Try to sync video every frame"), - _("This is relevant for progressive video only (most PAL films)."), 20, - dxr3_update_sync_mode, this); - this->enhanced_mode = cfg->register_bool(cfg, - "dxr3.alt_play_mode", 1, _("Use alternate Play mode"), - _("Enabling this option will utilise a smoother play mode."), 10, - dxr3_update_enhanced_mode, this); - this->correct_durations = cfg->register_bool(cfg, - "dxr3.correct_durations", 0, _("Correct frame durations in broken streams"), - _("Enable this for streams with wrong frame durations."), 10, - dxr3_update_correct_durations, this); - - /* set a/v offset to compensate dxr3 internal delay */ - cur_offset = this->xine->metronom->get_option(this->xine->metronom, METRONOM_AV_OFFSET); - this->xine->metronom->set_option(this->xine->metronom, METRONOM_AV_OFFSET, cur_offset - 21600); - - return &this->video_decoder; + return &this->video_decoder_class; } -static char *dxr3_get_id(void) +static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_stream_t *stream) { - return "dxr3-mpeg2"; -} - -static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out) -{ - dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; + dxr3_decoder_t *this; + dxr3_decoder_class_t *class = (dxr3_decoder_class_t *)class_gen; + config_values_t *cfg; char tmpstr[128]; + int64_t cur_offset; + + if (class->instance) return NULL; + if (!dxr3_present(stream)) return NULL; - snprintf(tmpstr, sizeof(tmpstr), "%s%s", this->devname, this->devnum); + this = (dxr3_decoder_t *)malloc(sizeof (dxr3_decoder_t)); + if (!this) return NULL; + + cfg = stream->xine->config; + + this->video_decoder.decode_data = dxr3_decode_data; + this->video_decoder.reset = dxr3_reset; + this->video_decoder.flush = dxr3_flush; + this->video_decoder.dispose = dxr3_dispose; + + this->class = class; + this->stream = stream; + this->scr = NULL; + this->dxr3_vo = (dxr3_driver_t *)stream->video_driver; + + snprintf(tmpstr, sizeof(tmpstr), "%s%s", class->devname, class->devnum); #if LOG_VID printf("dxr3_decode_video: Entering video init, devname=%s.\n",tmpstr); #endif @@ -216,12 +219,10 @@ static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out) if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { printf("dxr3_decode_video: Failed to open control device %s (%s)\n", tmpstr, strerror(errno)); - return; + free(this); + return NULL; } - video_out->open(video_out); - this->video_out = video_out; - this->have_header_info = 0; this->repeat_first_field = 0; @@ -236,11 +237,51 @@ static void dxr3_init(video_decoder_t *this_gen, vo_instance_t *video_out) this->skip_count = 0; this->force_duration_window = -FORCE_DURATION_WINDOW_SIZE; - this->last_vpts = - this->xine->metronom->get_current_time(this->xine->metronom); + this->last_vpts = this->stream->metronom->get_current_time(this->stream->metronom); this->avg_duration = 0; + + this->sync_every_frame = cfg->register_bool(cfg, + "dxr3.sync_every_frame", 0, _("Try to sync video every frame"), + _("This is relevant for progressive video only (most PAL films)."), 20, + dxr3_update_sync_mode, this); + this->enhanced_mode = cfg->register_bool(cfg, + "dxr3.alt_play_mode", 1, _("Use alternate Play mode"), + _("Enabling this option will utilise a smoother play mode."), 10, + dxr3_update_enhanced_mode, this); + this->correct_durations = cfg->register_bool(cfg, + "dxr3.correct_durations", 0, _("Correct frame durations in broken streams"), + _("Enable this for streams with wrong frame durations."), 10, + dxr3_update_correct_durations, this); + + if (!this->dxr3_vo->overlay_enabled) { + /* set a/v offset to compensate dxr3 internal delay */ + cur_offset = this->stream->metronom->get_option(this->stream->metronom, METRONOM_AV_OFFSET); + this->stream->metronom->set_option(this->stream->metronom, METRONOM_AV_OFFSET, cur_offset - 21600); + } + + stream->video_out->open(stream->video_out); + + class->instance = 1; + + return &this->video_decoder; +} + +static char *dxr3_get_identifier(video_decoder_class_t *class_gen) +{ + return "dxr3-mpeg2"; } +static char *dxr3_get_description(video_decoder_class_t *class_gen) +{ + return "MPEGI/II decoder plugin using the hardware decoding capabilities of a DXR3 decoder card."; +} + +static void dxr3_class_dispose(video_decoder_class_t *class_gen) +{ + free(class_gen); +} + + static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; @@ -262,12 +303,16 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) this->aspect = this->force_aspect = XINE_VO_ASPECT_PAN_SCAN; /* when aspect changed, we have to send an event for dxr3 spu decoder */ if (!this->last_aspect || this->last_aspect != this->aspect) { - xine_frame_change_event_t event; - event.event.type = XINE_EVENT_FRAME_CHANGE; - event.width = this->last_width; - event.height = this->last_height; - event.aspect = this->aspect; - xine_send_event(this->xine, &event.event); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = this->last_width; + data.height = this->last_height; + data.aspect = this->aspect; + xine_event_send(this->stream, &event); this->last_aspect = this->aspect; } } @@ -318,7 +363,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) continue; /* pretend like we have decoded a frame */ - img = this->video_out->get_frame (this->video_out, + img = this->stream->video_out->get_frame(this->stream->video_out, this->width, this->height, this->aspect, XINE_IMGFMT_DXR3, VO_BOTH_FIELDS); img->pts = buf->pts; @@ -364,7 +409,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) /* we have had enough skipping messages now, let's react */ int64_t vpts_adjust = skip * (int64_t)img->duration / 2; if (vpts_adjust > 90000) vpts_adjust = 90000; - this->xine->metronom->set_option(this->xine->metronom, + this->stream->metronom->set_option(this->stream->metronom, METRONOM_ADJ_VPTS_OFFSET, vpts_adjust); this->skip_count = 0; this->resync_window = 0; @@ -408,7 +453,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) */ if (this->fd_video < 0) { char tmpstr[128]; - snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum); + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->class->devname, this->class->devnum); if ((this->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK)) < 0) { printf("dxr3_decode_video: Failed to open video device %s (%s)\n", tmpstr, strerror(errno)); @@ -426,14 +471,13 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) if (!this->scr) { int64_t time; - time = this->xine->metronom->get_current_time( - this->xine->metronom); + time = this->stream->metronom->get_current_time(this->stream->metronom); - this->scr = dxr3_scr_init(this->xine); + this->scr = dxr3_scr_init(this->stream); this->scr->scr_plugin.start(&this->scr->scr_plugin, time); - this->xine->metronom->register_scr( - this->xine->metronom, &this->scr->scr_plugin); - if (this->xine->metronom->scr_master == &this->scr->scr_plugin) + this->stream->metronom->register_scr( + this->stream->metronom, &this->scr->scr_plugin); + if (this->stream->metronom->scr_master == &this->scr->scr_plugin) #if LOG_VID printf("dxr3_decode_video: dxr3_scr plugin is master\n"); #endif @@ -447,8 +491,8 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) if (vpts) { int64_t delay; - delay = vpts - this->xine->metronom->get_current_time( - this->xine->metronom); + delay = vpts - this->stream->metronom->get_current_time( + this->stream->metronom); #if LOG_PTS printf("dxr3_decode_video: SETPTS got %lld\n", vpts); #endif @@ -493,6 +537,10 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) written, buf->size); } +static void dxr3_reset(video_decoder_t *this_gen) +{ +} + static void dxr3_flush(video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; @@ -500,14 +548,10 @@ static void dxr3_flush(video_decoder_t *this_gen) if (this->fd_video >= 0) fsync(this->fd_video); } -static void dxr3_reset(video_decoder_t *this_gen) -{ -} - -static void dxr3_close(video_decoder_t *this_gen) +static void dxr3_dispose(video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; - metronom_t *metronom = this->xine->metronom; + metronom_t *metronom = this->stream->metronom; if (this->scr) { metronom->unregister_scr(metronom, &this->scr->scr_plugin); @@ -518,30 +562,33 @@ static void dxr3_close(video_decoder_t *this_gen) if (this->fd_video >= 0) close(this->fd_video); this->fd_video = -1; - this->video_out->close(this->video_out); + this->stream->video_out->close(this->stream->video_out); this->have_header_info = 0; -} - -static void dxr3_dispose(video_decoder_t *this_gen) -{ - free(this_gen); + this->class->instance = 0; + + free(this); } -static int dxr3_present(xine_t *xine) +static int dxr3_present(xine_stream_t *stream) { - int info; - - if (xine && xine->video_driver) { - info = xine->video_driver->get_property(xine->video_driver, VO_PROP_VO_TYPE); + plugin_node_t *node; + video_driver_class_t *vo_class; + int present = 0; + + if (stream->video_driver && stream->video_driver->node) { + node = (plugin_node_t *)stream->video_driver->node; + if (node->plugin_class) { + vo_class = (video_driver_class_t *)node->plugin_class; + if (vo_class->get_identifier) + present = (strcmp(vo_class->get_identifier(vo_class), DXR3_VO_ID) == 0); + } + } #ifdef LOG_VID - printf("dxr3_decode_video: dxr3 presence test: info = %d\n", info); + printf("dxr3_decode_video: dxr3 %s\n", present ? "present" : "not present"); #endif - if ((info != VO_TYPE_DXR3_LETTERBOXED) && (info != VO_TYPE_DXR3_WIDE)) - return 0; - } - return 1; + return present; } static int dxr3_mvcommand(int fd_control, int command) @@ -575,32 +622,36 @@ static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer) (this->last_width != this->width) || (this->last_height != this->height) || (this->last_aspect != this->aspect)) { - xine_frame_change_event_t event; - event.event.type = XINE_EVENT_FRAME_CHANGE; - event.width = this->width; - event.height = this->height; - event.aspect = this->aspect; - xine_send_event(this->xine, &event.event); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = this->width; + data.height = this->height; + data.aspect = this->aspect; + xine_event_send(this->stream, &event); this->last_width = this->width; this->last_height = this->height; this->last_aspect = this->aspect; /* update stream metadata */ - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height; switch (this->aspect) { case XINE_VO_ASPECT_SQUARE: - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000; break; case XINE_VO_ASPECT_4_3: - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 4.0 / 3.0; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 4.0 / 3.0; break; case XINE_VO_ASPECT_PAN_SCAN: case XINE_VO_ASPECT_ANAMORPHIC: - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 16.0 / 9.0; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 16.0 / 9.0; break; case XINE_VO_ASPECT_DVB: - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 2.11; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_RATIO] = 10000 * 2.11; break; } } @@ -643,7 +694,7 @@ static int get_duration(dxr3_decoder_t *this) } /* update stream metadata */ - this->xine->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = duration; + this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = duration; if (this->correct_durations) { /* we set an initial average frame duration here */ @@ -656,13 +707,13 @@ static int get_duration(dxr3_decoder_t *this) */ if (this->avg_duration && this->avg_duration < 3300 && duration == 3600) { if (this->force_duration_window > 0) { - // we are already in a force_duration window, so we force duration + /* we are already in a force_duration window, so we force duration */ this->force_duration_window = FORCE_DURATION_WINDOW_SIZE; return 3000; } if (this->force_duration_window <= 0 && (this->force_duration_window += 10) > 0) { - // we just entered a force_duration window, so we start the correction - metronom_t *metronom = this->xine->metronom; + /* we just entered a force_duration window, so we start the correction */ + metronom_t *metronom = this->stream->metronom; int64_t cur_offset; printf("dxr3_decode_video: WARNING: correcting frame rate code from PAL to NTSC\n"); /* those weird streams need an offset, too */ @@ -674,11 +725,11 @@ static int get_duration(dxr3_decoder_t *this) } if (this->force_duration_window == -FORCE_DURATION_WINDOW_SIZE) - // we are far from a force_duration window + /* we are far from a force_duration window */ return duration; if (--this->force_duration_window == 0) { - // we have just left a force_duration window - metronom_t *metronom = this->xine->metronom; + /* we have just left a force_duration window */ + metronom_t *metronom = this->stream->metronom; int64_t cur_offset; cur_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET); metronom->set_option(metronom, METRONOM_AV_OFFSET, cur_offset + 28800); diff --git a/src/dxr3/dxr3_mpeg_encoders.c b/src/dxr3/dxr3_mpeg_encoders.c index e661753b1..00a1dc2dc 100644 --- a/src/dxr3/dxr3_mpeg_encoders.c +++ b/src/dxr3/dxr3_mpeg_encoders.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3_mpeg_encoders.c,v 1.9 2002/09/05 12:52:24 mroi Exp $ + * $Id: dxr3_mpeg_encoders.c,v 1.10 2002/10/26 14:35:04 mroi Exp $ */ /* mpeg encoders for the dxr3 video out plugin. @@ -177,7 +177,7 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) return 0; } - this->rte_bitrate = drv->xine->config->register_range(drv->xine->config, + this->rte_bitrate = drv->class->xine->config->register_range(drv->class->xine->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"), 10, @@ -295,7 +295,7 @@ static void mp1e_callback(rte_context *context, void *data, ssize_t size, void * ssize_t written; if (drv->fd_video == CLOSED_FOR_ENCODER) { - snprintf(tmpstr, sizeof(tmpstr), "%s_mv%s", drv->devname, drv->devnum); + snprintf(tmpstr, sizeof(tmpstr), "%s_mv%s", drv->class->devname, drv->class->devnum); drv->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK); } if (drv->fd_video < 0) return; @@ -346,7 +346,7 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) /* if YUY2 and dimensions changed, we need to re-allocate the * internal YV12 buffer */ if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { - int image_size = drv->video_width * drv->video_oheight; + int image_size = frame->vo_frame.width * frame->oheight; this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, (void *)&this->buf); @@ -384,7 +384,7 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) } this->fp = init_fp; - this->fp.quality = drv->xine->config->register_range(drv->xine->config, + this->fp.quality = drv->class->xine->config->register_range(drv->class->xine->config, "dxr3.fame_quality", 90, 10, 100, _("Dxr3enc: fame mpeg encoding quality"), _("The encoding quality of the libfame mpeg encoder library."), 10, @@ -396,8 +396,8 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) 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.width = frame->vo_frame.width; + this->fp.height = frame->oheight; this->fp.profile = "mpeg1"; this->fp.coding = "I"; #if LOG_ENC @@ -484,7 +484,7 @@ static int fame_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) 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); + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", drv->class->devname, drv->class->devnum); drv->fd_video = open(tmpstr, O_WRONLY | O_NONBLOCK); } if (drv->fd_video < 0) return 0; diff --git a/src/dxr3/dxr3_scr.c b/src/dxr3/dxr3_scr.c index e78d0ae54..95cc41105 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.5 2002/09/05 12:52:24 mroi Exp $ + * $Id: dxr3_scr.c,v 1.6 2002/10/26 14:35:04 mroi Exp $ */ /* dxr3 scr plugin. @@ -31,7 +31,6 @@ #include <unistd.h> #include <errno.h> -#include "xineutils.h" #include "dxr3.h" #include "dxr3_scr.h" @@ -53,14 +52,14 @@ static int dxr3_mvcommand(int fd_control, int command); static void dxr3_scr_update_priority(void *this_gen, xine_cfg_entry_t *entry); -dxr3_scr_t *dxr3_scr_init(xine_t *xine) +dxr3_scr_t *dxr3_scr_init(xine_stream_t *stream) { dxr3_scr_t *this; const char *confstr; this = (dxr3_scr_t *)malloc(sizeof(dxr3_scr_t)); - confstr = xine->config->register_string(xine->config, + confstr = stream->xine->config->register_string(stream->xine->config, CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, 0, NULL, NULL); if ((this->fd_control = open(confstr, O_WRONLY)) < 0) { printf("dxr3_scr: Failed to open control device %s (%s)\n", @@ -77,8 +76,8 @@ dxr3_scr_t *dxr3_scr_init(xine_t *xine) this->scr_plugin.set_speed = dxr3_scr_set_speed; this->scr_plugin.exit = dxr3_scr_exit; - this->priority = xine->config->register_num( - xine->config, "dxr3.scr_priority", 10, _("Dxr3: SCR plugin priority"), + this->priority = stream->xine->config->register_num( + stream->xine->config, "dxr3.scr_priority", 10, _("Dxr3: SCR plugin priority"), _("Scr priorities greater 5 make the dxr3 xine's master clock."), 20, dxr3_scr_update_priority, this); this->offset = 0; @@ -132,6 +131,8 @@ static int64_t dxr3_scr_get_current(scr_plugin_t *scr) if (this->last_pts > 0xF0000000 && pts < 0x10000000) /* wrap around detected, compensate with offset */ this->offset += (int64_t)1 << 33; + if (pts == 0) + printf("dxr3_scr: WARNING: pts dropped to zero.\n"); this->last_pts = pts; current = ((int64_t)pts << 1) + this->offset; pthread_mutex_unlock(&this->mutex); diff --git a/src/dxr3/dxr3_scr.h b/src/dxr3/dxr3_scr.h index 8260ce3f0..c038feb90 100644 --- a/src/dxr3/dxr3_scr.h +++ b/src/dxr3/dxr3_scr.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dxr3_scr.h,v 1.2 2002/05/24 22:09:44 miguelfreitas Exp $ + * $Id: dxr3_scr.h,v 1.3 2002/10/26 14:35:05 mroi Exp $ */ #include "xine_internal.h" @@ -37,4 +37,4 @@ typedef struct dxr3_scr_s { } dxr3_scr_t; /* plugin initialization function */ -dxr3_scr_t *dxr3_scr_init(xine_t *xine); +dxr3_scr_t *dxr3_scr_init(xine_stream_t *stream); diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c index 9da93591b..df330b7cc 100644 --- a/src/dxr3/video_out_dxr3.c +++ b/src/dxr3/video_out_dxr3.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_out_dxr3.c,v 1.57 2002/10/11 10:55:27 mroi Exp $ + * $Id: video_out_dxr3.c,v 1.58 2002/10/26 14:35:05 mroi Exp $ */ /* mpeg1 encoding video out plugin for the dxr3. @@ -63,14 +63,13 @@ #define LOG_OVR 0 -/* plugin initialization function */ +/* plugin class initialization function */ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen); /* plugin catalog information */ static vo_info_t vo_info_dxr3 = { 10, /* priority */ - "dxr3", /* description */ XINE_VISUAL_TYPE_X11 /* visual type */ }; @@ -81,7 +80,13 @@ plugin_info_t xine_plugin_info[] = { }; -/* functions required by xine api */ +/* plugin class functions */ +static xine_vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const void *visual); +static char *dxr3_vo_get_identifier(video_driver_class_t *class_gen); +static char *dxr3_vo_get_description(video_driver_class_t *class_gen); +static void dxr3_vo_class_dispose(video_driver_class_t *class_gen); + +/* plugin instance functions */ static uint32_t dxr3_get_capabilities(xine_vo_driver_t *this_gen); static vo_frame_t *dxr3_alloc_frame(xine_vo_driver_t *this_gen); static void dxr3_frame_copy(vo_frame_t *frame_gen, uint8_t **src); @@ -102,10 +107,10 @@ static void dxr3_get_property_min_max(xine_vo_driver_t *this_gen, int pro int *min, int *max); static int dxr3_gui_data_exchange(xine_vo_driver_t *this_gen, int data_type, void *data); -static void dxr3_exit(xine_vo_driver_t *this_gen); +static void dxr3_dispose(xine_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 void gather_screen_vars(dxr3_driver_t *this, const 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); @@ -113,9 +118,6 @@ static int dxr3_overlay_set_attributes(dxr3_overlay_t *this); /* overlay helper functions */ 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, xine_cfg_entry_t *entry); @@ -125,18 +127,75 @@ static void dxr3_update_enhanced_mode(void *this_gen, xine_cfg_entry_t *e static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) { + dxr3_driver_class_t *this; + const char *confstr; + int dashpos; + + this = (dxr3_driver_class_t *)malloc(sizeof(dxr3_driver_class_t)); + if (!this) return NULL; + + confstr = xine->config->register_string(xine->config, + CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, 0, NULL, NULL); + strncpy(this->devname, confstr, 128); + this->devname[127] = '\0'; + dashpos = strlen(this->devname) - 2; /* the dash in the new device naming scheme would be here */ + if (this->devname[dashpos] == '-') { + /* use new device naming scheme with trailing number */ + strncpy(this->devnum, &this->devname[dashpos], 3); + this->devname[dashpos] = '\0'; + } else { + /* use old device naming scheme without trailing number */ + /* FIXME: remove this when everyone uses em8300 >=0.12.0 */ + this->devnum[0] = '\0'; + } + + this->video_driver_class.open_plugin = dxr3_vo_open_plugin; + this->video_driver_class.get_identifier = dxr3_vo_get_identifier; + this->video_driver_class.get_description = dxr3_vo_get_description; + this->video_driver_class.dispose = dxr3_vo_class_dispose; + + this->xine = xine; + + this->instance = 0; + + return &this->video_driver_class; +} + +static char *dxr3_vo_get_identifier(video_driver_class_t *class_gen) +{ + return DXR3_VO_ID; +} + +static char *dxr3_vo_get_description(video_driver_class_t *class_gen) +{ + return "video output plugin displaying images through your DXR3 decoder card"; +} + +static void dxr3_vo_class_dispose(video_driver_class_t *class_gen) +{ + free(class_gen); +} + + +static xine_vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const void *visual_gen) +{ dxr3_driver_t *this; + dxr3_driver_class_t *class = (dxr3_driver_class_t *)class_gen; + config_values_t *config = class->xine->config; char tmpstr[100]; const char *confstr; - int dashpos, encoder, confnum; + int encoder, confnum; static char *available_encoders[SUPPORTED_ENCODER_COUNT + 2]; #ifdef HAVE_X11 - static char *videoout_modes[] = { "letterboxed tv", "widescreen tv", "overlay", NULL }; + static char *videoout_modes[] = { "letterboxed tv", "widescreen tv", + "letterboxed overlay", "widescreen overlay", NULL }; #else static char *videoout_modes[] = { "letterboxed tv", "widescreen tv", NULL }; #endif static char *tv_modes[] = { "ntsc", "pal", "pal60" , "default", NULL }; + if (class->instance) return NULL; + this = (dxr3_driver_t *)malloc(sizeof(dxr3_driver_t)); if (!this) return NULL; memset(this, 0, sizeof(dxr3_driver_t)); @@ -153,40 +212,27 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) 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->vo_driver.dispose = dxr3_dispose; pthread_mutex_init(&this->spu_device_lock, NULL); - this->xine = xine; - this->swap_fields = xine->config->register_bool(xine->config, + vo_scale_init(&this->scale, 0, 0); + + this->class = class; + this->swap_fields = config->register_bool(config, "dxr3.enc_swap_fields", 0, _("swap odd and even lines"), NULL, 10, dxr3_update_swap_fields, this); - this->add_bars = xine->config->register_bool(xine->config, + 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."), 10, dxr3_update_add_bars, this); - this->enhanced_mode = xine->config->register_bool(xine->config, + 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."), 10, dxr3_update_enhanced_mode, this); - confstr = xine->config->register_string(xine->config, - CONF_LOOKUP, CONF_DEFAULT, CONF_NAME, CONF_HELP, 0, 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); + snprintf(tmpstr, sizeof(tmpstr), "%s%s", class->devname, class->devnum); #if LOG_VID printf("video_out_dxr3: Entering video init, devname = %s.\n", tmpstr); #endif @@ -196,7 +242,7 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) return 0; } - snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", this->devname, this->devnum); + snprintf (tmpstr, sizeof(tmpstr), "%s_mv%s", class->devname, class->devnum); if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) { printf("video_out_dxr3: Failed to open video device %s (%s)\n", tmpstr, strerror(errno)); @@ -229,8 +275,8 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) printf("none\n"); #endif if (encoder) { - encoder = xine->config->register_enum(xine->config, "dxr3.encoder", - 0, available_encoders, _("the encoder for non mpeg content"), + encoder = config->register_enum(config, "dxr3.encoder", 0, + available_encoders, _("the encoder for non mpeg content"), _("Content other than mpeg has to pass an additional reencoding stage, " "because the dxr3 handles mpeg only."), 10, NULL, NULL); #ifdef HAVE_LIBRTE @@ -258,17 +304,21 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) /* 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 = xine->config->register_range(xine->config, "dxr3.contrast", + 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, 0, NULL, NULL); - this->bcs.saturation = xine->config->register_range(xine->config, "dxr3.saturation", + this->bcs.saturation = config->register_range(config, "dxr3.saturation", this->bcs.saturation, 100, 900, _("Dxr3: saturation control"), NULL, 0, NULL, NULL); - this->bcs.brightness = xine->config->register_range(xine->config, "dxr3.brightness", + this->bcs.brightness = config->register_range(config, "dxr3.brightness", this->bcs.brightness, 100, 900, _("Dxr3: brightness control"), NULL, 0, NULL, NULL); - + if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs)) + printf("video_out_dxr3: cannot set bcs values (%s)\n", strerror(errno)); + + /* init aspect */ + dxr3_set_property(&this->vo_driver, VO_PROP_ASPECT_RATIO, ASPECT_FULL); + /* overlay or tvout? */ - confnum = xine->config->register_enum(xine->config, "dxr3.videoout_mode", 0, videoout_modes, + confnum = config->register_enum(config, "dxr3.videoout_mode", 0, videoout_modes, _("Dxr3: videoout mode (tv or overlay)"), NULL, 0, NULL, NULL); #if LOG_VID printf("video_out_dxr3: overlaymode = %s\n", videoout_modes[confnum]); @@ -282,12 +332,11 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) case 1: /* widescreen tv mode */ this->overlay_enabled = 0; this->tv_switchable = 0; /* don't allow on-the-fly switching */ - /* switch to fullscreen mode for ever, let the tv set do the anamorphic unsqueezing */ - dxr3_set_property(&this->vo_driver, VO_PROP_ASPECT_RATIO, ASPECT_FULL); this->widescreen_enabled = 1; break; #ifdef HAVE_X11 - case 2: /* overlay mode */ + case 2: /* letterboxed overlay mode */ + case 3: /* widescreen overlay mode */ #if LOG_VID printf("video_out_dxr3: setting up overlay mode\n"); #endif @@ -295,11 +344,11 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) if (dxr3_overlay_read_state(&this->overlay) == 0) { this->overlay_enabled = 1; this->tv_switchable = 1; - this->widescreen_enabled = 0; - confstr = xine->config->register_string(xine->config, "dxr3.keycolor", "0x80a040", + this->widescreen_enabled = confnum - 2; + confstr = config->register_string(config, "dxr3.keycolor", "0x80a040", _("Dxr3: overlay colorkey value"), NULL, 10, NULL, NULL); sscanf(confstr, "%x", &this->overlay.colorkey); - confstr = xine->config->register_string(xine->config, "dxr3.color_interval", "50.0", + confstr = config->register_string(config, "dxr3.color_interval", "50.0", _("Dxr3: overlay colorkey range"), _("A greater value widens the tolerance for the overlay keycolor"), 10, NULL, NULL); sscanf(confstr, "%f", &this->overlay.color_interval); @@ -313,7 +362,7 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) } /* init tvmode */ - confnum = xine->config->register_enum(xine->config, "dxr3.preferred_tvmode", 3, tv_modes, + confnum = config->register_enum(config, "dxr3.preferred_tvmode", 3, tv_modes, _("dxr3 preferred tv mode"), NULL, 0, NULL, NULL); switch (confnum) { case 0: /* ntsc */ @@ -346,14 +395,19 @@ static void *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) if (this->overlay_enabled) { em8300_overlay_screen_t scr; int value; + XColor dummy; 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); + this->key.red = ((this->overlay.colorkey >> 16) & 0xff) * 256; + this->key.green = ((this->overlay.colorkey >> 8) & 0xff) * 256; + this->key.blue = ((this->overlay.colorkey ) & 0xff) * 256; + XAllocColor(this->display, DefaultColormap(this->display, 0), &this->key); + + /* allocate black for output area borders */ + XAllocNamedColor(this->display, DefaultColormap(this->display, 0), + "black", &this->black, &dummy); /* set the screen */ scr.xsize = this->overlay.screen_xres; @@ -434,9 +488,6 @@ static void dxr3_update_frame_format(xine_vo_driver_t *this_gen, vo_frame_t *fra dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; int oheight; - /* update the overlay window co-ords if required */ - dxr3_overlay_update(this); - if (format == XINE_IMGFMT_DXR3) { /* talking to dxr3 decoder */ /* a bit of a hack. we must release the em8300_mv fd for * the dxr3 decoder plugin */ @@ -459,7 +510,6 @@ static void dxr3_update_frame_format(xine_vo_driver_t *this_gen, vo_frame_t *fra frame->vo_frame.height = height; frame->vo_frame.ratio = ratio_code; frame->oheight = height; - frame->pan_scan = (ratio_code == XINE_VO_ASPECT_PAN_SCAN); frame->aspect = 0; if (frame->mem) { @@ -481,7 +531,7 @@ static void dxr3_update_frame_format(xine_vo_driver_t *this_gen, vo_frame_t *fra if (this->fd_video == CLOSED_FOR_DECODER) { /* decoder should have released it */ this->fd_video = CLOSED_FOR_ENCODER; /* allow encoder to reopen it */ - this->need_redraw = 1; + this->scale.force_redraw = 1; } if (this->add_bars == 0) { @@ -502,6 +552,10 @@ static void dxr3_update_frame_format(xine_vo_driver_t *this_gen, vo_frame_t *fra frame->aspect = ASPECT_ANAMORPHIC; oheight = height; break; + case XINE_VO_ASPECT_DVB: + frame->aspect = ASPECT_ANAMORPHIC; + oheight = height * 2.11 * 9.0 / 16.0; + break; default: /* assume square pixel */ frame->aspect = ASPECT_ANAMORPHIC; oheight = (int)(width * 9./16.); @@ -520,12 +574,12 @@ static void dxr3_update_frame_format(xine_vo_driver_t *this_gen, vo_frame_t *fra printf("video_out_dxr3: adding %d black lines to get %s aspect ratio.\n", oheight - height, frame->aspect == ASPECT_FULL ? "4:3" : "16:9"); - this->video_width = width; - this->video_iheight = height; - this->video_oheight = oheight; - this->video_ratio = ratio_code; - this->need_redraw = 1; - this->need_update = 1; + this->video_width = width; + this->video_iheight = height; + this->video_oheight = oheight; + this->video_ratio = ratio_code; + this->scale.force_redraw = 1; + this->need_update = 1; if (!this->enc) { /* no encoder plugin! Let's bug the user! */ @@ -669,7 +723,7 @@ static void dxr3_overlay_end(xine_vo_driver_t *this_gen, vo_frame_t *frame_gen) /* try to open the dxr3 spu device */ if (!this->fd_spu) { - snprintf (tmpstr, sizeof(tmpstr), "%s_sp%s", this->devname, this->devnum); + snprintf (tmpstr, sizeof(tmpstr), "%s_sp%s", this->class->devname, this->class->devnum); if ((this->fd_spu = open (tmpstr, O_WRONLY)) < 0) { printf("video_out_dxr3: Failed to open spu device %s (%s)\n", tmpstr, strerror(errno)); @@ -750,8 +804,9 @@ static void dxr3_display_frame(xine_vo_driver_t *this_gen, vo_frame_t *frame_gen frame->aspect = ASPECT_ANAMORPHIC; } } - if (frame->aspect != this->aspect) - dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, frame->aspect); + if ((this->widescreen_enabled ? ASPECT_FULL : frame->aspect) != this->aspect) + dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, + (this->widescreen_enabled ? ASPECT_FULL : frame->aspect)); if (frame->pan_scan && !this->pan_scan) { dxr3_set_property(this_gen, VO_PROP_ZOOM_X, 1); this->pan_scan = 1; @@ -761,6 +816,26 @@ static void dxr3_display_frame(xine_vo_driver_t *this_gen, vo_frame_t *frame_gen dxr3_set_property(this_gen, VO_PROP_ZOOM_X, -1); } + if (this->overlay_enabled) { + if (this->scale.force_redraw || + this->scale.delivered_width != frame_gen->width || + this->scale.delivered_height != frame->oheight || + this->scale.delivered_ratio_code != frame_gen->ratio || + this->scale.user_ratio != (this->widescreen_enabled ? frame->aspect : ASPECT_FULL)) { + + this->scale.delivered_width = frame_gen->width; + this->scale.delivered_height = frame->oheight; + this->scale.delivered_ratio_code = frame_gen->ratio; + this->scale.user_ratio = (this->widescreen_enabled ? frame->aspect : ASPECT_FULL); + this->scale.force_redraw = 1; + + vo_scale_compute_ideal_size(&this->scale); + + /* prepare the overlay window */ + dxr3_overlay_update(this); + } + } + if (frame_gen->format != XINE_IMGFMT_DXR3 && this->enc && this->enc->on_display_frame) { if (this->need_update) { /* we cannot do this earlier, because vo_frame.duration is only valid here */ @@ -780,7 +855,9 @@ static int dxr3_redraw_needed(xine_vo_driver_t *this_gen) { dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - dxr3_overlay_update(this); + if (this->overlay_enabled) + dxr3_overlay_update(this); + return 0; } @@ -803,10 +880,6 @@ static int dxr3_get_property(xine_vo_driver_t *this_gen, int property) case VO_PROP_ZOOM_Y: case VO_PROP_TVMODE: return 0; - case VO_PROP_VO_TYPE: - if (this->overlay_enabled && is_fullscreen(this)) return VO_TYPE_DXR3_LETTERBOXED; - if (this->overlay_enabled || this->widescreen_enabled) return VO_TYPE_DXR3_WIDE; - return VO_TYPE_DXR3_LETTERBOXED; } printf("video_out_dxr3: property %d not implemented.\n", property); return 0; @@ -816,7 +889,6 @@ static int dxr3_set_property(xine_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: @@ -842,17 +914,12 @@ static int dxr3_set_property(xine_vo_driver_t *this_gen, int property, int value * can switch to 16:9 mode. I don't know if the dxr3 can do this. */ break; } - 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) - /* FIXME: Is it necessary to switch to anamorphic mode in fullscreen? */ - val = EM8300_ASPECTRATIO_16_9; - else /* The overlay window can adapt to the ratio */ - val = EM8300_ASPECTRATIO_4_3; + val = EM8300_ASPECTRATIO_16_9; } else { #if LOG_VID printf("video_out_dxr3: setting aspect ratio to full\n"); @@ -863,7 +930,7 @@ static int dxr3_set_property(xine_vo_driver_t *this_gen, int property, int value if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val)) printf("video_out_dxr3: failed to set aspect ratio (%s)\n", strerror(errno)); - dxr3_overlay_update(this); + this->scale.force_redraw = 1; break; case VO_PROP_COLORKEY: printf("video_out_dxr3: VO_PROP_COLORKEY not implemented!"); @@ -908,9 +975,9 @@ static int dxr3_set_property(xine_vo_driver_t *this_gen, int property, int value 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->xine->config->update_num(this->xine->config, "dxr3.contrast", this->bcs.contrast); - this->xine->config->update_num(this->xine->config, "dxr3.saturation", this->bcs.saturation); - this->xine->config->update_num(this->xine->config, "dxr3.brightness", this->bcs.brightness); + this->class->xine->config->update_num(this->class->xine->config, "dxr3.contrast", this->bcs.contrast); + this->class->xine->config->update_num(this->class->xine->config, "dxr3.saturation", this->bcs.saturation); + this->class->xine->config->update_num(this->class->xine->config, "dxr3.brightness", this->bcs.brightness); } return value; @@ -941,8 +1008,7 @@ static int dxr3_gui_data_exchange(xine_vo_driver_t *this_gen, int data_type, voi switch (data_type) { case XINE_GUI_SEND_EXPOSE_EVENT: - this->need_redraw = 1; - dxr3_overlay_update(this); + this->scale.force_redraw = 1; break; case XINE_GUI_SEND_DRAWABLE_CHANGED: this->win = (Drawable)data; @@ -954,10 +1020,10 @@ static int dxr3_gui_data_exchange(xine_vo_driver_t *this_gen, int data_type, voi { 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); + vo_scale_translate_gui2video(&this->scale, rect->x, rect->y, &x1, &y1); + vo_scale_translate_gui2video(&this->scale, rect->x + rect->w, rect->y + rect->h, &x2, &y2); rect->x = x1; - rect->y = y1; + rect->y = y1 - this->top_bar; rect->w = x2 - x1; rect->h = y2 - y1; } @@ -978,7 +1044,7 @@ static int dxr3_gui_data_exchange(xine_vo_driver_t *this_gen, int data_type, voi #endif val = EM8300_OVERLAY_MODE_OVERLAY; this->overlay_enabled = 1; - this->need_redraw = 1; + this->scale.force_redraw = 1; } ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &val); dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, this->aspect); @@ -991,7 +1057,7 @@ static int dxr3_gui_data_exchange(xine_vo_driver_t *this_gen, int data_type, voi return 0; } -static void dxr3_exit(xine_vo_driver_t *this_gen) +static void dxr3_dispose(xine_vo_driver_t *this_gen) { dxr3_driver_t *this = (dxr3_driver_t *)this_gen; int val = EM8300_OVERLAY_MODE_OFF; @@ -1011,7 +1077,7 @@ static void dxr3_exit(xine_vo_driver_t *this_gen) #ifdef HAVE_X11 -static void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis) +static void gather_screen_vars(dxr3_driver_t *this, const x11_visual_t *vis) { int scrn; #ifdef HAVE_XINERAMA @@ -1020,11 +1086,11 @@ static void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis) XineramaScreenInfo *screeninfo = NULL; #endif - this->win = vis->d; - this->display = vis->display; - this->user_data = vis->user_data; - this->gc = XCreateGC(this->display, this->win, 0, NULL); - scrn = DefaultScreen(this->display); + this->win = vis->d; + this->display = vis->display; + this->scale.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) && @@ -1039,8 +1105,8 @@ static void gather_screen_vars(dxr3_driver_t *this, x11_visual_t *vis) this->overlay.screen_yres = DisplayHeight(this->display, scrn); } - this->overlay.screen_depth = DisplayPlanes(this->display, scrn); - this->frame_output_cb = (void *)vis->frame_output_cb; + this->overlay.screen_depth = DisplayPlanes(this->display, scrn); + this->scale.frame_output_cb = (void *)vis->frame_output_cb; #if LOG_OVR printf("video_out_dxr3: xres: %d, yres: %d, depth: %d\n", @@ -1254,58 +1320,36 @@ static int dxr3_overlay_set_attributes(dxr3_overlay_t *this) static void dxr3_overlay_update(dxr3_driver_t *this) { - if (this->overlay_enabled) { - double video_aspect, gui_aspect; - int gui_win_x, gui_win_y, win_off_x, win_off_y, gui_width, gui_height; + if (vo_scale_redraw_needed(&this->scale)) { + em8300_overlay_window_t win; - switch (this->aspect) { - case ASPECT_FULL: - video_aspect = 4 / 3; - break; - case ASPECT_ANAMORPHIC: - video_aspect = 16 / 9; - break; - default: - video_aspect = 4 / 3; - } + vo_scale_compute_output_size(&this->scale); - this->frame_output_cb(this->user_data, - this->video_width, this->video_oheight, video_aspect, - &win_off_x, &win_off_y, &gui_width, &gui_height, &gui_aspect, &gui_win_x, &gui_win_y); - - if (this->xpos != (gui_win_x + win_off_x) || - this->ypos != (gui_win_y + win_off_y) || - this->width != gui_width || - this->height != gui_height || - this->need_redraw) { - em8300_overlay_window_t win; - - this->xpos = gui_win_x + win_off_x; - this->ypos = gui_win_y + win_off_y; - this->width = gui_width; - this->height = gui_height; + /* fill video window with keycolor */ + XLockDisplay(this->display); + XSetForeground(this->display, this->gc, this->black.pixel); + XFillRectangle(this->display, this->win, this->gc, + this->scale.gui_x, this->scale.gui_y, + this->scale.gui_width, this->scale.gui_height); + XSetForeground(this->display, this->gc, this->key.pixel); + XFillRectangle(this->display, this->win, this->gc, + this->scale.output_xoffset, this->scale.output_yoffset, + this->scale.output_width, this->scale.output_height); + XFlush(this->display); + XUnlockDisplay(this->display); - /* fill video window with keycolor */ - XLockDisplay(this->display); - XSetForeground(this->display, this->gc, this->color.pixel); - XFillRectangle(this->display, this->win, this->gc, - win_off_x, win_off_y, this->width, this->height); - XUnlockDisplay(this->display); - this->need_redraw = 0; - - /* is some part of the picture visible? */ - if (this->xpos + this->width < 0) return; - if (this->ypos + this->height < 0) return; - if (this->xpos > this->overlay.screen_xres) return; - if (this->ypos > this->overlay.screen_yres) return; + win.xpos = this->scale.output_xoffset + this->scale.gui_win_x; + win.ypos = this->scale.output_yoffset + this->scale.gui_win_y; + win.width = this->scale.output_width; + win.height = this->scale.output_height; + + /* is some part of the picture visible? */ + if (win.xpos + win.width < 0) return; + if (win.ypos + win.height < 0) return; + if (win.xpos > this->overlay.screen_xres) return; + if (win.ypos > this->overlay.screen_yres) return; - win.xpos = this->xpos; - win.ypos = this->ypos; - win.width = this->width; - win.height = this->height; - - ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETWINDOW, &win); - } + ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETWINDOW, &win); } } #endif @@ -1349,32 +1393,6 @@ static void dxr3_zoomTV(dxr3_driver_t *this) ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update); } -#ifdef HAVE_X11 -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; -} -#endif - -static int is_fullscreen(dxr3_driver_t *this) -{ -#ifdef HAVE_X11 - 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; -#else - return 0; -#endif -} - static void dxr3_update_add_bars(void *data, xine_cfg_entry_t *entry) { diff --git a/src/dxr3/video_out_dxr3.h b/src/dxr3/video_out_dxr3.h index 17507bcf5..83d7f80d2 100644 --- a/src/dxr3/video_out_dxr3.h +++ b/src/dxr3/video_out_dxr3.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_dxr3.h,v 1.11 2002/10/11 10:55:28 mroi Exp $ + * $Id: video_out_dxr3.h,v 1.12 2002/10/26 14:35:05 mroi Exp $ */ #ifdef HAVE_CONFIG_H @@ -29,6 +29,7 @@ #endif #include "xine_internal.h" +#include "vo_scale.h" #include "dxr3.h" /* values for fd_video indicating why it is closed */ @@ -68,58 +69,59 @@ typedef struct dxr3_overlay_s { struct coeff colcal_lower[3]; } dxr3_overlay_t; -typedef struct dxr3_driver_s { - xine_vo_driver_t vo_driver; - xine_t *xine; +typedef struct dxr3_driver_class_s { + video_driver_class_t video_driver_class; + xine_t *xine; + + int instance; /* we allow only one instance of this plugin */ + + char devname[128]; + char devnum[3]; +} dxr3_driver_class_t; - char devname[128]; - char devnum[3]; - int fd_control; - int fd_video; - pthread_mutex_t spu_device_lock; - int fd_spu; /* to access the relevant dxr3 devices */ - int clut_cluttered;/* to tell spu decoder that it has to restore the palette */ +typedef struct dxr3_driver_s { + xine_vo_driver_t vo_driver; + dxr3_driver_class_t *class; + + int fd_control; + int fd_video; + pthread_mutex_t spu_device_lock; + int fd_spu; /* to access the relevant dxr3 devices */ + int clut_cluttered; /* to tell spu decoder that it has to restore the palette */ + + int enhanced_mode; + int swap_fields; /* swap fields */ + int add_bars; /* add black bars to correct a.r. */ - int enhanced_mode; - int swap_fields; /* swap fields */ - int add_bars; /* add black bars to correct a.r. */ + int aspect; + int tv_mode; + int pan_scan; + int overlay_enabled; + int tv_switchable; /* can switch from overlay<->tvout */ + int widescreen_enabled; + em8300_bcs_t bcs; + + encoder_data_t *enc; /* mpeg encoder data */ + spu_encoder_t *spu_enc; /* spu encoder */ + int need_update; /* the mpeg encoder needs to be updated */ - int aspect; - int tv_mode; - int pan_scan; - int overlay_enabled; - int tv_switchable; /* can switch from overlay<->tvout */ - int widescreen_enabled; - em8300_bcs_t bcs; - - encoder_data_t *enc; /* mpeg encoder data */ - spu_encoder_t *spu_enc; /* spu encoder */ - int video_iheight; /* input height (before adding black bars) */ - int video_oheight; /* output height (after adding bars) */ - int video_width; - int video_ratio; - 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; + int video_iheight; /* input height (before adding black bars) */ + int video_oheight; /* output height (after adding black bars) */ + int video_width; + int video_ratio; + int top_bar; /* the height of the upper black bar */ + + vo_scale_t scale; + + dxr3_overlay_t overlay; #ifdef HAVE_X11 - Display *display; - Drawable win; - GC gc; - XColor color; - int xpos, ypos; - int width, height; + Display *display; + Drawable win; + GC gc; + XColor black; + XColor key; #endif - char *user_data; - void (*frame_output_cb)(void *user_data, - int video_width, int video_height, - double video_pixel_aspect, - int *dest_x, int *dest_y, - int *dest_height, int *dest_width, - double *dest_pixel_aspect, - int *win_x, int *win_y); } dxr3_driver_t; typedef struct dxr3_frame_s { |