summaryrefslogtreecommitdiff
path: root/src/xine-engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine')
-rw-r--r--src/xine-engine/Makefile.am4
-rw-r--r--src/xine-engine/video_out.h7
-rw-r--r--src/xine-engine/vo_scale.c336
-rw-r--r--src/xine-engine/vo_scale.h178
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
+