diff options
Diffstat (limited to 'src/xine-engine')
-rw-r--r-- | src/xine-engine/Makefile.am | 4 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 7 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.c | 336 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.h | 178 |
4 files changed, 520 insertions, 5 deletions
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 0180cc3d6..b7d7174a4 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -14,14 +14,14 @@ endif libxine_la_SOURCES = $(nvtv) xine.c metronom.c configfile.c buffer.c \ load_plugins.c video_decoder.c buffer_types.c \ audio_decoder.c video_out.c audio_out.c resample.c events.c lrb.c \ - video_overlay.c osd.c scratch.c locale.c demux.c + video_overlay.c osd.c scratch.c locale.c demux.c vo_scale.c libxine_la_DEPENDENCIES = @INTLLIBS@ libxine_la_LIBADD = $(THREAD_LIBS) $(DYNAMIC_LD_LIBS) @INTLLIBS@ $(ZLIB_LIBS) -lm libxine_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -include_HEADERS = buffer.h metronom.h configfile.h \ +include_HEADERS = buffer.h metronom.h configfile.h vo_scale.h \ audio_out.h resample.h video_out.h xine_internal.h spu_decoder.h \ events.h lrb.h video_overlay.h osd.h scratch.h xineintl.h diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 9c7e6bf78..0d0ba633b 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.h,v 1.57 2002/08/10 21:25:20 miguelfreitas Exp $ + * $Id: video_out.h,v 1.58 2002/08/15 03:12:26 miguelfreitas Exp $ * * * xine version of video_out.h @@ -186,12 +186,13 @@ struct vo_instance_s { #define VO_PROP_BRIGHTNESS 5 #define VO_PROP_COLORKEY 6 #define VO_PROP_AUTOPAINT_COLORKEY 7 -#define VO_PROP_ZOOM_FACTOR 8 +#define VO_PROP_ZOOM_X 8 #define VO_PROP_PAN_SCAN 9 #define VO_PROP_TVMODE 10 #define VO_PROP_MAX_NUM_FRAMES 11 #define VO_PROP_VO_TYPE 12 -#define VO_NUM_PROPERTIES 13 +#define VO_PROP_ZOOM_Y 13 +#define VO_NUM_PROPERTIES 14 /* Video out types */ #define VO_TYPE_UNKNOWN 0 diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c new file mode 100644 index 000000000..40639c9aa --- /dev/null +++ b/src/xine-engine/vo_scale.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: vo_scale.c,v 1.1 2002/08/15 03:12:27 miguelfreitas Exp $ + * + * Contains common code to calculate video scaling parameters. + * In short, it will map frame dimensions to screen/window size. + * Takes into account aspect ratio correction and zooming. + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "xine_internal.h" +#include "video_out.h" +#include "vo_scale.h" + +/* +#define LOG +*/ + +/* + * convert delivered height/width to ideal width/height + * taking into account aspect ratio and zoom factor + */ + +void vo_scale_compute_ideal_size (vo_scale_t *this) { + + double image_ratio, desired_ratio, corr_factor; + + if (this->scaling_disabled) { + + this->ideal_width = this->delivered_width; + this->ideal_height = this->delivered_height; + + } else { + + /* + * aspect ratio + */ + + image_ratio = (double) this->delivered_width / (double) this->delivered_height; + + switch (this->user_ratio) { + case ASPECT_AUTO: + switch (this->delivered_ratio_code) { + case XINE_ASPECT_RATIO_ANAMORPHIC: /* anamorphic */ + case XINE_ASPECT_RATIO_PAN_SCAN: /* we display pan&scan as widescreen */ + desired_ratio = 16.0 /9.0; + break; + case XINE_ASPECT_RATIO_211_1: /* 2.11:1 */ + desired_ratio = 2.11/1.0; + break; + case XINE_ASPECT_RATIO_SQUARE: /* square pels */ + case XINE_ASPECT_RATIO_DONT_TOUCH: /* probably non-mpeg stream => don't touch aspect ratio */ + desired_ratio = image_ratio; + break; + case 0: /* forbidden -> 4:3 */ + printf ("vo_scale: invalid ratio, using 4:3\n"); + default: + printf ("vo_scale: unknown aspect ratio (%d) in stream => using 4:3\n", + this->delivered_ratio_code); + case XINE_ASPECT_RATIO_4_3: /* 4:3 */ + desired_ratio = 4.0 / 3.0; + break; + } + break; + case ASPECT_ANAMORPHIC: + desired_ratio = 16.0 / 9.0; + break; + case ASPECT_DVB: + desired_ratio = 2.0 / 1.0; + break; + case ASPECT_SQUARE: + desired_ratio = image_ratio; + break; + case ASPECT_FULL: + default: + desired_ratio = 4.0 / 3.0; + } + + corr_factor = this->display_ratio * desired_ratio / image_ratio ; + + if (fabs(corr_factor - 1.0) < 0.005) { + this->ideal_width = this->delivered_width; + this->ideal_height = this->delivered_height; + + } else { + + if (corr_factor >= 1.0) { + this->ideal_width = this->delivered_width * corr_factor + 0.5; + this->ideal_height = this->delivered_height; + } else { + this->ideal_width = this->delivered_width; + this->ideal_height = this->delivered_height / corr_factor + 0.5; + } + } + } +} + + +/* + * make ideal width/height "fit" into the gui + */ + +void vo_scale_compute_output_size (vo_scale_t *this) { + + double x_factor, y_factor; + + x_factor = (double) this->gui_width / (double) this->ideal_width; + y_factor = (double) this->gui_height / (double) this->ideal_height; + + if ( this->support_zoom ) { + + /* zoom behaviour: + * - window size never changes due zooming + * - output image shall be increased whenever there are + * black borders to use. + * - exceding zoom shall be accounted by reducing displayed image. + */ + if ( x_factor <= y_factor ) { + this->output_width = this->gui_width; + this->displayed_width = this->delivered_width / this->zoom_factor_x; + + this->output_height = this->ideal_height * x_factor; + if( this->output_height * this->zoom_factor_y <= this->gui_height ) { + this->displayed_height = this->delivered_height; + this->output_height = this->output_height * this->zoom_factor_y; + } else { + this->displayed_height = (double) this->delivered_height * + this->gui_height / this->output_height / this->zoom_factor_y; + this->output_height = this->gui_height; + } + } else { + this->output_height = this->gui_height; + this->displayed_height = this->delivered_height / this->zoom_factor_y; + + this->output_width = this->ideal_width * y_factor; + if( this->output_width * this->zoom_factor_x <= this->gui_width ) { + this->displayed_width = this->delivered_width; + this->output_width = this->output_width * this->zoom_factor_x; + } else { + this->displayed_width = (double) this->delivered_width * + this->gui_width / this->output_width / this->zoom_factor_x; + this->output_width = this->gui_width; + } + } + + } else { + if(x_factor < y_factor) { + this->output_width = (double) this->gui_width; + this->output_height = (double) this->ideal_height * x_factor; + } else { + this->output_width = (double) this->ideal_width * y_factor; + this->output_height = (double) this->gui_height; + } + } + + this->output_xoffset = (this->gui_width - this->output_width) / 2 + this->gui_x; + this->output_yoffset = (this->gui_height - this->output_height) / 2 + this->gui_y; + + this->displayed_xoffset = (this->delivered_width - this->displayed_width) / 2; + this->displayed_yoffset = (this->delivered_height - this->displayed_height) / 2; + +#ifdef LOG + printf ("vo_scale: frame source %d x %d (%d x %d) => screen output %d x %d\n", + this->delivered_width, this->delivered_height, + this->displayed_width, this->displayed_height, + this->output_width, this->output_height); +#endif + + + /* calculate borders */ + if (this->output_height != this->gui_height) { + /* top */ + this->border[0].x = 0; + this->border[0].y = 0; + this->border[0].w = this->gui_width; + this->border[0].h = this->output_yoffset; + /* bottom */ + this->border[1].x = 0; + this->border[1].y = this->output_yoffset + this->output_height; + this->border[1].w = this->gui_width; + this->border[1].h = this->gui_height - this->border[1].y; + } else { + /* no top/bottom borders */ + this->border[0].w = this->border[0].h = 0; + this->border[1].w = this->border[1].h = 0; + } + + if (this->output_width != this->gui_width) { + /* left */ + this->border[2].x = 0; + this->border[2].y = 0; + this->border[2].w = this->output_xoffset; + this->border[2].h = this->gui_height; + /* right */ + this->border[3].x = this->output_xoffset + this->output_width;; + this->border[3].y = 0; + this->border[3].w = this->gui_width - this->border[3].x; + this->border[3].h = this->gui_height; + } else { + /* no left/right borders */ + this->border[2].w = this->border[2].h = 0; + this->border[3].w = this->border[3].h = 0; + } +} + +/* + * return true if a redraw is needed due resizing, zooming, + * aspect ratio changing, etc. + */ + +int vo_scale_redraw_needed (vo_scale_t *this) { + int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y; + int ret = 0; + + if( this->frame_output_cb ) { + this->frame_output_cb (this->user_data, + this->ideal_width, this->ideal_height, + &gui_x, &gui_y, &gui_width, &gui_height, + &gui_win_x, &gui_win_y ); + } else { + printf ("vo_scale: error! frame_output_cb must be set!\n"); + } + + if ( (gui_x != this->gui_x) || (gui_y != this->gui_y) + || (gui_width != this->gui_width) || (gui_height != this->gui_height) + || (gui_win_x != this->gui_win_x) || (gui_win_y != this->gui_win_y) ) { + + this->gui_x = gui_x; + this->gui_y = gui_y; + this->gui_width = gui_width; + this->gui_height = gui_height; + this->gui_win_x = gui_win_x; + this->gui_win_y = gui_win_y; + + ret = 1; + } + else + ret = this->force_redraw; + + this->force_redraw = 0; + return ret; +} + +/* + * + */ + +void vo_scale_translate_gui2video(vo_scale_t *this, + int x, int y, + int *vid_x, int *vid_y) { + + if (this->output_width > 0 && this->output_height > 0) { + /* + * 1. + * the driver may center a small output area inside a larger + * gui area. This is the case in fullscreen mode, where we often + * have black borders on the top/bottom/left/right side. + */ + x -= this->output_xoffset; + y -= this->output_yoffset; + + /* + * 2. + * the driver scales the delivered area into an output area. + * translate output area coordianates into the delivered area + * coordiantes. + */ + x = x * this->delivered_width / this->output_width; + y = y * this->delivered_height / this->output_height; + + /* FIXME: not that trivial, must take zoom into account */ + } + + *vid_x = x; + *vid_y = y; +} + +/* + * Returns description of a given ratio code + */ + +char *vo_scale_aspect_ratio_name(int a) { + + switch (a) { + case ASPECT_AUTO: + return "auto"; + case ASPECT_SQUARE: + return "square"; + case ASPECT_FULL: + return "4:3"; + case ASPECT_ANAMORPHIC: + return "16:9"; + case ASPECT_DVB: + return "2:1"; + default: + return "unknown"; + } +} + + +/* + * initialize rescaling struct + */ + +void vo_scale_init(vo_scale_t *this, double display_ratio, + int support_zoom, int scaling_disabled ) { + + memset( this, 0, sizeof(vo_scale_t) ); + this->display_ratio = display_ratio; + this->support_zoom = support_zoom; + this->scaling_disabled = scaling_disabled; + this->force_redraw = 1; + this->zoom_factor_x = 1.0; + this->zoom_factor_y = 1.0; +} + diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h new file mode 100644 index 000000000..934da69e5 --- /dev/null +++ b/src/xine-engine/vo_scale.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: vo_scale.h,v 1.1 2002/08/15 03:12:27 miguelfreitas Exp $ + * + * vo_scale.h + * + * keeps video scaling information + */ + +#ifndef HAVE_VO_SCALE_H +#define HAVE_VO_SCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +typedef struct { + int x, y; + int w, h; +} vo_scale_rect_t; + +struct vo_scale_s { + + /* display anatomy */ + double display_ratio; /* given by visual parameter + from init function */ + + /* true if driver supports frame zooming */ + int support_zoom; + + /* forces direct mapping between frame pixels and screen pixels */ + int scaling_disabled; + + /* size / aspect ratio calculations */ + + /* + * "delivered" size: + * frame dimension / aspect as delivered by the decoder + * used (among other things) to detect frame size changes + * units: frame pixels + */ + int delivered_width; + int delivered_height; + int delivered_ratio_code; + + /* + * displayed part of delivered images, + * taking zoom into account + * units: frame pixels + */ + int displayed_xoffset; + int displayed_yoffset; + int displayed_width; + int displayed_height; + double zoom_factor_x, zoom_factor_y; + + /* + * "ideal" size : + * delivered width/height corrected by aspect ratio and display_ratio + * units: screen pixels + */ + int ideal_width, ideal_height; + int user_ratio; + + /* + * "gui" size / offset: + * what gui told us about where to display the video + * units: screen pixels + */ + int gui_x, gui_y; + int gui_width, gui_height; + int gui_win_x, gui_win_y; + + /* + * "output" size: + * + * this is finally the ideal size "fitted" into the + * gui size while maintaining the aspect ratio + * units: screen pixels + */ + int output_width; + int output_height; + int output_xoffset; + int output_yoffset; + + /* */ + int force_redraw; + + + /* gui callbacks */ + + void *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); + + void (*dest_size_cb) (void *user_data, + int video_width, int video_height, + int *dest_width, int *dest_height); + + /* borders */ + vo_scale_rect_t border[4]; +}; + +typedef struct vo_scale_s vo_scale_t; + + +/* + * convert delivered height/width to ideal width/height + * taking into account aspect ratio and zoom factor + */ + +void vo_scale_compute_ideal_size (vo_scale_t *this); + + +/* + * make ideal width/height "fit" into the gui + */ + +void vo_scale_compute_output_size (vo_scale_t *this); + +/* + * return true if a redraw is needed due resizing, zooming, + * aspect ratio changing, etc. + */ + +int vo_scale_redraw_needed (vo_scale_t *this); + +/* + * + */ + +void vo_scale_translate_gui2video(vo_scale_t *this, + int x, int y, + int *vid_x, int *vid_y); + +/* + * Returns description of a given ratio code + */ + +char *vo_scale_aspect_ratio_name(int a); + +/* + * initialize rescaling struct + */ + +void vo_scale_init(vo_scale_t *this, double display_ratio, + int support_zoom, int scaling_disabled ); + +#ifdef __cplusplus +} +#endif + +#endif + |