summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-08-15 03:12:24 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-08-15 03:12:24 +0000
commitfcb74c4f0e6fc5a1deec0839c773067d0a8b9e90 (patch)
tree154b7d6ac8ddf1e6c52b2f256c4c2f2713be8ba5 /src
parent1b2d20cd85bd3ea8735a1fbc4ea7f68dafdfe23d (diff)
downloadxine-lib-fcb74c4f0e6fc5a1deec0839c773067d0a8b9e90.tar.gz
xine-lib-fcb74c4f0e6fc5a1deec0839c773067d0a8b9e90.tar.bz2
- reimplement independent x/y zooming.
- new helper module (vo_scale.c) with all common scaling code of video out drivers. it should greatly simplify drivers development by removing the boring frame/window calculation, aspect ratio, zooming etc. obs: not completely tested, may contain bugs and break things. also only xshm and xv have being simplified so far, others will follow shortly. CVS patchset: 2455 CVS date: 2002/08/15 03:12:24
Diffstat (limited to 'src')
-rw-r--r--src/dxr3/video_out_dxr3.c9
-rw-r--r--src/video_out/video_out_syncfb.c8
-rw-r--r--src/video_out/video_out_xshm.c469
-rw-r--r--src/video_out/video_out_xv.c370
-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
8 files changed, 712 insertions, 669 deletions
diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c
index e038abe74..ed6e8df9c 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.48 2002/08/13 15:44:02 mroi Exp $
+ * $Id: video_out_dxr3.c,v 1.49 2002/08/15 03:12:25 miguelfreitas Exp $
*/
/* mpeg1 encoding video out plugin for the dxr3.
@@ -652,12 +652,12 @@ static void dxr3_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen)
if (frame->aspect != this->aspect)
dxr3_set_property(this_gen, VO_PROP_ASPECT_RATIO, frame->vo_frame.ratio);
if (frame->pan_scan && !this->pan_scan) {
- dxr3_set_property(this_gen, VO_PROP_ZOOM_FACTOR, 1);
+ dxr3_set_property(this_gen, VO_PROP_ZOOM_X, 1);
this->pan_scan = 1;
}
if (!frame->pan_scan && this->pan_scan) {
this->pan_scan = 0;
- dxr3_set_property(this_gen, VO_PROP_ZOOM_FACTOR, -1);
+ dxr3_set_property(this_gen, VO_PROP_ZOOM_X, -1);
}
if (frame_gen->format != IMGFMT_MPEG && this->enc && this->enc->on_display_frame) {
@@ -698,7 +698,8 @@ static int dxr3_get_property(vo_driver_t *this_gen, int property)
return this->aspect;
case VO_PROP_COLORKEY:
return this->overlay.colorkey;
- case VO_PROP_ZOOM_FACTOR:
+ case VO_PROP_ZOOM_X:
+ case VO_PROP_ZOOM_Y:
case VO_PROP_TVMODE:
return 0;
case VO_PROP_VO_TYPE:
diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c
index 07ab6e82b..4c5c29372 100644
--- a/src/video_out/video_out_syncfb.c
+++ b/src/video_out/video_out_syncfb.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_syncfb.c,v 1.74 2002/08/10 21:25:20 miguelfreitas Exp $
+ * $Id: video_out_syncfb.c,v 1.75 2002/08/15 03:12:24 miguelfreitas Exp $
*
* video_out_syncfb.c, SyncFB (for Matrox G200/G400 cards) interface for xine
*
@@ -414,7 +414,7 @@ static void syncfb_compute_ideal_size (syncfb_driver_t *this)
/*
* zoom
*/
- zoom_factor = (double)this->props[VO_PROP_ZOOM_FACTOR].value / (double)VO_ZOOM_STEP;
+ zoom_factor = (double)this->props[VO_PROP_ZOOM_X].value / (double)VO_ZOOM_STEP;
this->displayed_width = this->delivered_width / zoom_factor;
this->displayed_height = this->delivered_height / zoom_factor;
@@ -840,7 +840,7 @@ static int syncfb_set_property(vo_driver_t* this_gen, int property, int value)
syncfb_clean_output_area(this);
break;
- case VO_PROP_ZOOM_FACTOR:
+ case VO_PROP_ZOOM_X:
#ifdef DEBUG_OUTPUT
printf("video_out_syncfb: debug. (VO_PROP_ZOOM %d <=? %d <=? %d)\n",
VO_ZOOM_MIN, value, VO_ZOOM_MAX);
@@ -1044,7 +1044,7 @@ vo_driver_t *init_video_out_plugin(config_values_t *config, void *visual_gen)
this->props[VO_PROP_INTERLACED].value = 0;
this->props[VO_PROP_ASPECT_RATIO].value = ASPECT_AUTO;
- this->props[VO_PROP_ZOOM_FACTOR].value = 100;
+ this->props[VO_PROP_ZOOM_X].value = 100;
/* check for formats we need... */
this->supported_capabilities = 0;
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c
index fcc4a4089..84ca28525 100644
--- a/src/video_out/video_out_xshm.c
+++ b/src/video_out/video_out_xshm.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_xshm.c,v 1.83 2002/08/10 21:25:20 miguelfreitas Exp $
+ * $Id: video_out_xshm.c,v 1.84 2002/08/15 03:12:25 miguelfreitas Exp $
*
* video_out_xshm.c, X11 shared memory extension interface for xine
*
@@ -58,6 +58,7 @@
#include "alphablend.h"
#include "yuv2rgb.h"
#include "xineutils.h"
+#include "vo_scale.h"
/*
#define LOG
@@ -69,38 +70,11 @@ typedef struct xshm_frame_s {
vo_frame_t vo_frame;
/* frame properties as delivered by the decoder: */
- int width, height;
- int ratio_code;
+ /* obs: for width/height use vo_scale_t struct */
int format;
int flags;
- int user_ratio;
-
- /*
- * "ideal" size of this frame :
- * width/height corrected by aspect ratio
- */
-
- int ideal_width, ideal_height;
-
- /*
- * "gui" size of this frame:
- * what gui told us about how much room we have
- * to display this frame on
- */
-
- int gui_width, gui_height;
-
- /*
- * "output" size of this frame:
- * this is finally the ideal size "fitted" into the
- * gui size while maintaining the aspect ratio
- */
-
- int output_width, output_height;
-
-
- double ratio_factor;/* ideal/rgb size must fulfill: height = width * ratio_factor */
+ vo_scale_t sc;
XImage *image;
XShmSegmentInfo shminfo;
@@ -135,44 +109,14 @@ typedef struct xshm_driver_s {
int yuv2rgb_gamma;
uint8_t *yuv2rgb_cmap;
yuv2rgb_factory_t *yuv2rgb_factory;
- int user_ratio;
-
- /* force update screen if gamma changes */
- int force_redraw;
-
- /* speed tradeoffs */
- int scaling_disabled;
+ vo_scale_t sc;
+
int expecting_event; /* completion event */
xshm_frame_t *cur_frame; /* for completion event handling */
vo_overlay_t *overlay;
- /* video pos/size in gui window */
- int gui_x;
- int gui_y;
- int gui_width;
- int gui_height;
- int gui_win_x;
- int gui_win_y;
-
- /* aspect ratio of pixels on screen */
- double display_ratio;
-
- void *user_data;
-
- /* gui callbacks */
-
- 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);
-
} xshm_driver_t;
@@ -425,6 +369,7 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) {
}
memset (frame, 0, sizeof(xshm_frame_t));
+ memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
pthread_mutex_init (&frame->vo_frame.mutex, NULL);
@@ -449,110 +394,25 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) {
static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) {
- if (this->scaling_disabled) {
-
- frame->ideal_width = frame->width;
- frame->ideal_height = frame->height;
- frame->ratio_factor = 1.0;
-
- } else {
-
- double image_ratio, desired_ratio, corr_factor;
-
- image_ratio = (double) frame->width / (double) frame->height;
-
- switch (frame->user_ratio) {
- case ASPECT_AUTO:
- switch (frame->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 ("video_out_xshm: invalid ratio, using 4:3\n");
- default:
- printf ("video_out_xshm: unknown aspect ratio (%d) in stream => using 4:3\n",
- frame->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;
- }
-
- frame->ratio_factor = this->display_ratio * desired_ratio;
-
- /* compiler bug? using frame->ratio_factor here gave me
- some wrong numbers. */
- corr_factor = this->display_ratio * desired_ratio / image_ratio ;
-
- if (fabs(corr_factor - 1.0) < 0.005) {
- frame->ideal_width = frame->width;
- frame->ideal_height = frame->height;
-
- } else {
-
- if (corr_factor >= 1.0) {
- frame->ideal_width = frame->width * corr_factor + 0.5;
- frame->ideal_height = frame->height;
- } else {
- frame->ideal_width = frame->width;
- frame->ideal_height = frame->height / corr_factor + 0.5;
- }
- }
- }
+ vo_scale_compute_ideal_size( &frame->sc );
}
static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) {
- double x_factor, y_factor;
-
- /*
- * make the frame fit into the given destination area
- */
-
- x_factor = (double) frame->gui_width / (double) frame->ideal_width;
- y_factor = (double) frame->gui_height / (double) frame->ideal_height;
-
- if ( x_factor < y_factor ) {
- frame->output_width = (double) frame->ideal_width * x_factor ;
- frame->output_height = (double) frame->ideal_height * x_factor ;
- } else {
- frame->output_width = (double) frame->ideal_width * y_factor ;
- frame->output_height = (double) frame->ideal_height * y_factor ;
- }
+ vo_scale_compute_output_size( &frame->sc );
/* avoid problems in yuv2rgb */
- if (frame->output_height < ((frame->height + 15) >> 4))
- frame->output_height = ((frame->height + 15) >> 4);
- if (frame->output_width < 8)
- frame->output_width = 8;
+ if (frame->sc.output_height < ((frame->sc.delivered_height + 15) >> 4))
+ frame->sc.output_height = ((frame->sc.delivered_height + 15) >> 4);
+ if (frame->sc.output_width < 8)
+ frame->sc.output_width = 8;
#ifdef LOG
printf("video_out_xshm: frame source %d x %d => screen output %d x %d%s\n",
- frame->width, frame->height,
- frame->output_width, frame->output_height,
- ( frame->width != frame->output_width
- || frame->height != frame->output_height
+ frame->sc.delivered_width, frame->sc.delivered_height,
+ frame->sc.output_width, frame->sc.output_height,
+ ( frame->sc.delivered_width != frame->sc.output_width
+ || frame->sc.delivered_height != frame->sc.output_height
? ", software scaling"
: "" )
);
@@ -575,12 +435,12 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
do_adapt = 0;
- if ((width != frame->width)
- || (height != frame->height)
- || (ratio_code != frame->ratio_code)
+ if ((width != frame->sc.delivered_width)
+ || (height != frame->sc.delivered_height)
+ || (ratio_code != frame->sc.delivered_ratio_code)
|| (flags != frame->flags)
|| (format != frame->format)
- || (this->user_ratio != frame->user_ratio)) {
+ || (this->sc.user_ratio != frame->sc.user_ratio)) {
do_adapt = 1;
@@ -588,27 +448,27 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
printf ("video_out_xshm: frame format (from decoder) has changed => adapt\n");
#endif
- frame->width = width;
- frame->height = height;
- frame->ratio_code = ratio_code;
- frame->flags = flags;
- frame->format = format;
- frame->user_ratio = this->user_ratio;
+ frame->sc.delivered_width = width;
+ frame->sc.delivered_height = height;
+ frame->sc.delivered_ratio_code = ratio_code;
+ frame->flags = flags;
+ frame->format = format;
+ frame->sc.user_ratio = this->sc.user_ratio;
xshm_compute_ideal_size (this, frame);
}
/* ask gui what output size we'll have for this frame*/
- this->dest_size_cb (this->user_data, frame->ideal_width, frame->ideal_height,
+ this->sc.dest_size_cb (this->sc.user_data, frame->sc.ideal_width, frame->sc.ideal_height,
&gui_width, &gui_height);
- if ((frame->gui_width != gui_width) || (frame->gui_height != gui_height)
+ if ((frame->sc.gui_width != gui_width) || (frame->sc.gui_height != gui_height)
|| do_adapt) {
do_adapt = 1;
- frame->gui_width = gui_width;
- frame->gui_height = gui_height;
+ frame->sc.gui_width = gui_width;
+ frame->sc.gui_height = gui_height;
xshm_compute_rgb_size (this, frame);
@@ -624,7 +484,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
#ifdef LOG
printf ("video_out_xshm: updating frame to %d x %d\n",
- frame->output_width, frame->output_height);
+ frame->sc.output_width, frame->sc.output_height);
#endif
XLockDisplay (this->display);
@@ -654,7 +514,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
}
frame->image = create_ximage (this, &frame->shminfo,
- frame->output_width, frame->output_height);
+ frame->sc.output_width, frame->sc.output_height);
XUnlockDisplay (this->display);
@@ -662,17 +522,17 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
- frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, &frame->chunk[0]);
- frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), &frame->chunk[1]);
- frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), &frame->chunk[2]);
+ frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);
+ frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]);
+ frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]);
} else {
frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
- frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, &frame->chunk[0]);
+ frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);
frame->chunk[1] = NULL;
frame->chunk[2] = NULL;
}
- frame->stripe_height = 16 * frame->output_height / frame->height;
+ frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height;
/* printf ("video_out_xshm: stripe height is %d\n", frame->stripe_height); */
@@ -684,22 +544,22 @@ static void xshm_update_frame_format (vo_driver_t *this_gen,
case VO_TOP_FIELD:
case VO_BOTTOM_FIELD:
frame->yuv2rgb->configure (frame->yuv2rgb,
- frame->width,
+ frame->sc.delivered_width,
16,
2*frame->vo_frame.pitches[0],
2*frame->vo_frame.pitches[1],
- frame->output_width,
+ frame->sc.output_width,
frame->stripe_height,
frame->image->bytes_per_line*2);
frame->yuv_stride = frame->image->bytes_per_line*2;
break;
case VO_BOTH_FIELDS:
frame->yuv2rgb->configure (frame->yuv2rgb,
- frame->width,
+ frame->sc.delivered_width,
16,
frame->vo_frame.pitches[0],
frame->vo_frame.pitches[1],
- frame->output_width,
+ frame->sc.output_width,
frame->stripe_height,
frame->image->bytes_per_line);
frame->yuv_stride = frame->image->bytes_per_line;
@@ -746,18 +606,18 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo
switch (this->bpp) {
case 16:
blend_rgb16 ((uint8_t *)frame->image->data, overlay,
- frame->output_width, frame->output_height,
- frame->width, frame->height);
+ frame->sc.output_width, frame->sc.output_height,
+ frame->sc.delivered_width, frame->sc.delivered_height);
break;
case 24:
blend_rgb24 ((uint8_t *)frame->image->data, overlay,
- frame->output_width, frame->output_height,
- frame->width, frame->height);
+ frame->sc.output_width, frame->sc.output_height,
+ frame->sc.delivered_width, frame->sc.delivered_height);
break;
case 32:
blend_rgb32 ((uint8_t *)frame->image->data, overlay,
- frame->output_width, frame->output_height,
- frame->width, frame->height);
+ frame->sc.output_width, frame->sc.output_height,
+ frame->sc.delivered_width, frame->sc.delivered_height);
break;
default:
/* it should never get here */
@@ -766,81 +626,42 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo
}
}
-static void clean_output_area (xshm_driver_t *this) {
+static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) {
+ int i;
+
+ memcpy( this->sc.border, frame->sc.border, sizeof(this->sc.border) );
+
XLockDisplay (this->display);
XSetForeground (this->display, this->gc, this->black.pixel);
-
- XFillRectangle(this->display, this->drawable, this->gc,
- this->gui_x, this->gui_y,
- this->gui_width, this->gui_height);
-
-#if 0
- int xoffset, yoffset;
-
- xoffset = (this->gui_width - frame->output_width) / 2 + this->gui_x;
- yoffset = (this->gui_height - frame->output_height) / 2 + this->gui_y;
-
- /* top black band */
- XFillRectangle(this->display, this->drawable, this->gc,
- this->gui_x, this->gui_y,
- this->gui_width, yoffset - this->gui_y);
-
- /* left black band */
- XFillRectangle(this->display, this->drawable, this->gc,
- this->gui_x, this->gui_y,
- xoffset-this->gui_x, this->gui_height);
-
- /* bottom black band */
- XFillRectangle(this->display, this->drawable, this->gc,
- this->gui_x, yoffset+frame->output_height,
- this->gui_width, this->gui_height - yoffset - frame->output_height);
-
- /* right black band */
- XFillRectangle(this->display, this->drawable, this->gc,
- xoffset+frame->output_width, this->gui_y,
- this->gui_width - xoffset - frame->output_width, this->gui_height);
-#endif
+ for( i = 0; i < 4; i++ ) {
+ if( this->sc.border[i].w && this->sc.border[i].h )
+ XFillRectangle(this->display, this->drawable, this->gc,
+ this->sc.border[i].x, this->sc.border[i].y,
+ this->sc.border[i].w, this->sc.border[i].h);
+ }
XUnlockDisplay (this->display);
}
static int xshm_redraw_needed (vo_driver_t *this_gen) {
xshm_driver_t *this = (xshm_driver_t *) this_gen;
- int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y;
int ret = 0;
if( this->cur_frame ) {
-
- this->frame_output_cb (this->user_data,
- this->cur_frame->ideal_width, this->cur_frame->ideal_height,
- &gui_x, &gui_y, &gui_width, &gui_height,
- &gui_win_x, &gui_win_y );
-
- if ( (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) ) {
-
- 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;
-
- clean_output_area (this);
+
+ this->sc.ideal_width = this->cur_frame->sc.ideal_width;
+ this->sc.ideal_height = this->cur_frame->sc.ideal_height;
+ if( vo_scale_redraw_needed( &this->sc ) ) {
+
+ clean_output_area (this, this->cur_frame);
ret = 1;
}
}
else
ret = 1;
-
- if( this->force_redraw )
- ret = 1;
return ret;
}
@@ -849,8 +670,6 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
xshm_driver_t *this = (xshm_driver_t *) this_gen;
xshm_frame_t *frame = (xshm_frame_t *) frame_gen;
- int xoffset;
- int yoffset;
#ifdef LOG
printf ("video_out_xshm: display frame...\n");
@@ -865,11 +684,9 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
frame->vo_frame.displayed (&frame->vo_frame);
} else {
- int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y;
-
#ifdef LOG
printf ("video_out_xshm: about to draw frame %d x %d...\n",
- frame->output_width, frame->output_height);
+ frame->sc.output_width, frame->sc.output_height);
#endif
/*
@@ -877,42 +694,24 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
* ask for offset
*/
- this->frame_output_cb (this->user_data,
- frame->ideal_width, frame->ideal_height,
- &gui_x, &gui_y, &gui_width, &gui_height,
- &gui_win_x, &gui_win_y);
-
- if ( (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) ) {
-
- 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;
-
- clean_output_area (this);
+ this->sc.ideal_width = frame->sc.ideal_width;
+ this->sc.ideal_height = frame->sc.ideal_height;
+ if( vo_scale_redraw_needed( &this->sc ) ) {
+
+ clean_output_area (this, frame);
}
if (this->cur_frame) {
- if ( (this->cur_frame->output_width != frame->output_width)
- || (this->cur_frame->output_height != frame->output_height) )
- clean_output_area (this);
+ if ( (this->cur_frame->sc.output_width != frame->sc.output_width)
+ || (this->cur_frame->sc.output_height != frame->sc.output_height) )
+ clean_output_area (this, frame);
this->cur_frame->vo_frame.displayed (&this->cur_frame->vo_frame);
}
this->cur_frame = frame;
- this->force_redraw = 0;
- xoffset = (this->gui_width - frame->output_width) / 2 + this->gui_x;
- yoffset = (this->gui_height - frame->output_height) / 2 + this->gui_y;
-
XLockDisplay (this->display);
#ifdef LOG
printf ("video_out_xshm: display locked...\n");
@@ -925,8 +724,8 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
#endif
XShmPutImage(this->display,
this->drawable, this->gc, frame->image,
- 0, 0, xoffset, yoffset,
- frame->output_width, frame->output_height, True);
+ 0, 0, frame->sc.output_xoffset, frame->sc.output_yoffset,
+ frame->sc.output_width, frame->sc.output_height, True);
this->expecting_event = 10;
@@ -940,8 +739,8 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
XPutImage(this->display,
this->drawable, this->gc, frame->image,
- 0, 0, xoffset, yoffset,
- frame->output_width, frame->output_height);
+ 0, 0, frame->sc.output_xoffset, frame->sc.output_yoffset,
+ frame->sc.output_width, frame->sc.output_height);
XFlush(this->display);
}
@@ -961,7 +760,7 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) {
switch (property) {
case VO_PROP_ASPECT_RATIO:
- return this->user_ratio ;
+ return this->sc.user_ratio ;
case VO_PROP_MAX_NUM_FRAMES:
return 15;
case VO_PROP_BRIGHTNESS:
@@ -974,24 +773,6 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) {
return 0;
}
-static char *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";
- }
-}
-
static int xshm_set_property (vo_driver_t *this_gen,
int property, int value) {
@@ -1001,16 +782,16 @@ static int xshm_set_property (vo_driver_t *this_gen,
if (value>=NUM_ASPECT_RATIOS)
value = ASPECT_AUTO;
- this->user_ratio = value;
+ this->sc.user_ratio = value;
printf ("video_out_xshm: aspect ratio changed to %s\n",
- aspect_ratio_name(value));
+ vo_scale_aspect_ratio_name(value));
} else if ( property == VO_PROP_BRIGHTNESS) {
this->yuv2rgb_gamma = value;
this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, value);
- this->force_redraw = 1;
+ this->sc.force_redraw = 1;
#ifdef LOG
printf ("video_out_xshm: gamma changed to %d\n",value);
#endif
@@ -1034,36 +815,6 @@ static void xshm_get_property_min_max (vo_driver_t *this_gen,
}
}
-
-static void xshm_translate_gui2video (xshm_driver_t *this,
- xshm_frame_t * frame,
- int x, int y,
- int *vid_x, int *vid_y) {
-
- if ( (frame->output_width > 0) && (frame->output_height > 0)) {
- /*
- * 1.
- * the xshm 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->gui_width - frame->output_width) >> 1) + this->gui_x;
- y -= ((this->gui_height - frame->output_height) >> 1) + this->gui_y;
-
- /*
- * 2.
- * the xshm driver scales the delivered area into an output area.
- * translate output area coordianates into the delivered area
- * coordiantes.
- */
- x = x * frame->width / frame->output_width;
- y = y * frame->height / frame->output_height;
- }
-
- *vid_x = x;
- *vid_y = y;
-}
-
static int xshm_gui_data_exchange (vo_driver_t *this_gen,
int data_type, void *data) {
@@ -1098,49 +849,35 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen,
if (this->cur_frame) {
XExposeEvent * xev = (XExposeEvent *) data;
- int xoffset;
- int yoffset;
if (xev->count == 0) {
+ int i;
XLockDisplay (this->display);
- xoffset = (this->cur_frame->gui_width - this->cur_frame->output_width) / 2;
- yoffset = (this->cur_frame->gui_height - this->cur_frame->output_height) / 2;
-
if (this->use_shm) {
XShmPutImage(this->display,
this->drawable, this->gc, this->cur_frame->image,
- 0, 0, xoffset, yoffset,
- this->cur_frame->output_width, this->cur_frame->output_height,
+ 0, 0, this->cur_frame->sc.output_xoffset, this->cur_frame->sc.output_yoffset,
+ this->cur_frame->sc.output_width, this->cur_frame->sc.output_height,
False);
} else {
XPutImage(this->display,
this->drawable, this->gc, this->cur_frame->image,
- 0, 0, xoffset, yoffset,
- this->cur_frame->output_width, this->cur_frame->output_height);
+ 0, 0, this->cur_frame->sc.output_xoffset, this->cur_frame->sc.output_yoffset,
+ this->cur_frame->sc.output_width, this->cur_frame->sc.output_height);
}
XSetForeground (this->display, this->gc, this->black.pixel);
- if (this->cur_frame->output_height != this->cur_frame->gui_height) {
- int y = yoffset + this->cur_frame->output_height;
-
- XFillRectangle(this->display, this->drawable, this->gc, 0, 0,
- this->cur_frame->gui_width, yoffset);
- XFillRectangle(this->display, this->drawable, this->gc, 0, y,
- this->cur_frame->gui_width, (this->cur_frame->gui_height - y));
- }
- if (this->cur_frame->output_width != this->cur_frame->gui_width) {
- int x = xoffset + this->cur_frame->output_width;
-
- XFillRectangle(this->display, this->drawable, this->gc, 0, yoffset,
- xoffset, this->cur_frame->output_height);
- XFillRectangle(this->display, this->drawable, this->gc, x, yoffset,
- (this->cur_frame->gui_width - x), this->cur_frame->output_height);
+ for( i = 0; i < 4; i++ ) {
+ if( this->sc.border[i].w && this->sc.border[i].h )
+ XFillRectangle(this->display, this->drawable, this->gc,
+ this->sc.border[i].x, this->sc.border[i].y,
+ this->sc.border[i].w, this->sc.border[i].h);
}
XFlush (this->display);
@@ -1167,10 +904,10 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen,
x11_rectangle_t *rect = data;
int x1, y1, x2, y2;
- xshm_translate_gui2video(this, this->cur_frame,
+ vo_scale_translate_gui2video(&this->sc,
rect->x, rect->y,
&x1, &y1);
- xshm_translate_gui2video(this, this->cur_frame,
+ vo_scale_translate_gui2video(&this->sc,
rect->x + rect->w, rect->y + rect->h,
&x2, &y2);
rect->x = x1;
@@ -1286,17 +1023,15 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
this->config = config;
this->display = visual->display;
this->screen = visual->screen;
- this->display_ratio = visual->display_ratio;
- this->frame_output_cb = visual->frame_output_cb;
- this->dest_size_cb = visual->dest_size_cb;
- this->user_data = visual->user_data;
- this->gui_x = 0;
- this->gui_y = 0;
- this->gui_width = 0;
- this->gui_height = 0;
- this->user_ratio = ASPECT_AUTO;
+
+ vo_scale_init( &this->sc, visual->display_ratio, 0, 0 );
+ this->sc.frame_output_cb = visual->frame_output_cb;
+ this->sc.dest_size_cb = visual->dest_size_cb;
+ this->sc.user_data = visual->user_data;
+
+ this->sc.user_ratio = ASPECT_AUTO;
- this->scaling_disabled = config->register_bool (config, "video.disable_scaling", 0,
+ this->sc.scaling_disabled = config->register_bool (config, "video.disable_scaling", 0,
_("disable all video scaling (faster!)"),
NULL, NULL, NULL);
this->drawable = visual->d;
diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c
index 0ea7b1919..e2ef7f4b6 100644
--- a/src/video_out/video_out_xv.c
+++ b/src/video_out/video_out_xv.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_xv.c,v 1.125 2002/08/10 21:25:20 miguelfreitas Exp $
+ * $Id: video_out_xv.c,v 1.126 2002/08/15 03:12:25 miguelfreitas Exp $
*
* video_out_xv.c, X11 video extension interface for xine
*
@@ -64,6 +64,7 @@
#include "alphablend.h"
#include "deinterlace.h"
#include "xineutils.h"
+#include "vo_scale.h"
/*
#define LOG
@@ -112,11 +113,7 @@ struct xv_driver_s {
XColor black;
int expecting_event; /* completion event handling */
int use_shm;
- /* display anatomy */
- double display_ratio; /* given by visual parameter
- from init function */
-
-
+
xv_property_t props[VO_NUM_PROPERTIES];
uint32_t capabilities;
@@ -124,74 +121,13 @@ struct xv_driver_s {
xv_frame_t *cur_frame;
vo_overlay_t *overlay;
- /* size / aspect ratio calculations */
-
- /*
- * "delivered" size:
- * frame dimension / aspect as delivered by the decoder
- * used (among other things) to detect frame size changes
- */
- int delivered_width;
- int delivered_height;
- int delivered_ratio_code;
- int delivered_duration;
-
- /*
- * displayed part of delivered images,
- * taking zoom into account
- */
-
- int displayed_xoffset;
- int displayed_yoffset;
- int displayed_width;
- int displayed_height;
-
- /*
- * "ideal" size :
- * displayed width/height corrected by aspect ratio
- */
-
- int ideal_width, ideal_height;
- double ratio_factor; /* output frame must fullfill:
- height = width * ratio_factor */
-
- /*
- * "gui" size / offset:
- * what gui told us about where to display the video
- */
+ /* all scaling information goes here */
+ vo_scale_t sc;
- 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
- *
- */
-
- /* Window */
- int output_width;
- int output_height;
- int output_xoffset;
- int output_yoffset;
-
xv_frame_t deinterlace_frame;
int deinterlace_method;
int deinterlace_enabled;
- void *user_data;
-
- /* gui callback */
-
- 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);
-
char scratch[256];
int use_colorkey;
@@ -589,13 +525,13 @@ static void xv_clean_output_area (xv_driver_t *this) {
XSetForeground (this->display, this->gc, this->black.pixel);
XFillRectangle(this->display, this->drawable, this->gc,
- this->gui_x, this->gui_y, this->gui_width, this->gui_height);
+ this->sc.gui_x, this->sc.gui_y, this->sc.gui_width, this->sc.gui_height);
if (this->use_colorkey) {
XSetForeground (this->display, this->gc, this->colorkey);
XFillRectangle (this->display, this->drawable, this->gc,
- this->output_xoffset, this->output_yoffset,
- this->output_width, this->output_height);
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
}
XUnlockDisplay (this->display);
@@ -608,91 +544,7 @@ static void xv_clean_output_area (xv_driver_t *this) {
static void xv_compute_ideal_size (xv_driver_t *this) {
- double zoom_factor;
- double image_ratio, desired_ratio, corr_factor;
-
- /*
- * zoom
- */
-
- zoom_factor = (double)this->props[VO_PROP_ZOOM_FACTOR].value / (double)VO_ZOOM_STEP;
-
- this->displayed_width = this->delivered_width / zoom_factor;
- this->displayed_height = this->delivered_height / zoom_factor;
- this->displayed_xoffset = (this->delivered_width - this->displayed_width) / 2;
- this->displayed_yoffset = (this->delivered_height - this->displayed_height) / 2;
-
-
- /*
- * aspect ratio
- */
-
- image_ratio = (double) this->delivered_width / (double) this->delivered_height;
-
- switch (this->props[VO_PROP_ASPECT_RATIO].value) {
- 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 ("video_out_xv: invalid ratio, using 4:3\n");
- default:
- printf ("video_out_xv: 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;
- }
-
- this->ratio_factor = this->display_ratio * desired_ratio;
-
- corr_factor = this->ratio_factor / 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;
- }
- }
-
- /* onefield_xv divide by 2 the number of lines */
- if (this->deinterlace_enabled
- && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
- && (this->cur_frame->format == IMGFMT_YV12)) {
- this->displayed_height = this->displayed_height / 2;
- this->displayed_yoffset = this->displayed_yoffset / 2;
- }
+ vo_scale_compute_ideal_size( &this->sc );
}
@@ -702,28 +554,15 @@ static void xv_compute_ideal_size (xv_driver_t *this) {
static void xv_compute_output_size (xv_driver_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;
+ vo_scale_compute_output_size( &this->sc );
- 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;
+ /* onefield_xv divide by 2 the number of lines */
+ if (this->deinterlace_enabled
+ && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
+ && (this->cur_frame->format == IMGFMT_YV12)) {
+ this->sc.displayed_height = this->sc.displayed_height / 2;
+ this->sc.displayed_yoffset = this->sc.displayed_yoffset / 2;
}
-
- 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;
-
-#ifdef LOG
- printf ("video_out_xv: frame source %d x %d => screen output %d x %d\n",
- this->delivered_width, this->delivered_height,
- this->output_width, this->output_height);
-#endif
-
}
static void xv_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) {
@@ -774,24 +613,9 @@ static void xv_flush_recent_frames (xv_driver_t *this) {
static int xv_redraw_needed (vo_driver_t *this_gen) {
xv_driver_t *this = (xv_driver_t *) this_gen;
- int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y;
int ret = 0;
- 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 );
-
- 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;
+ if( vo_scale_redraw_needed( &this->sc ) ) {
xv_compute_output_size (this);
@@ -842,21 +666,20 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
* ratio from the previous one
*/
- if ( (frame->width != this->delivered_width)
- || (frame->height != this->delivered_height)
- || (frame->ratio_code != this->delivered_ratio_code) ) {
+ if ( (frame->width != this->sc.delivered_width)
+ || (frame->height != this->sc.delivered_height)
+ || (frame->ratio_code != this->sc.delivered_ratio_code) ) {
#ifdef LOG
printf("video_out_xv: frame format changed\n");
#endif
- this->delivered_width = frame->width;
- this->delivered_height = frame->height;
- this->delivered_ratio_code = frame->ratio_code;
- this->delivered_duration = frame->vo_frame.duration;
+ this->sc.delivered_width = frame->width;
+ this->sc.delivered_height = frame->height;
+ this->sc.delivered_ratio_code = frame->ratio_code;
xv_compute_ideal_size (this);
- this->gui_width = 0; /* trigger re-calc of output size */
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
}
/*
@@ -870,19 +693,19 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
if (this->use_shm) {
XvShmPutImage(this->display, this->xv_port,
this->drawable, this->gc, this->cur_frame->image,
- this->displayed_xoffset, this->displayed_yoffset,
- this->displayed_width, this->displayed_height,
- this->output_xoffset, this->output_yoffset,
- this->output_width, this->output_height, True);
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height, True);
this->expecting_event = 10;
} else {
XvPutImage(this->display, this->xv_port,
this->drawable, this->gc, this->cur_frame->image,
- this->displayed_xoffset, this->displayed_yoffset,
- this->displayed_width, this->displayed_height,
- this->output_xoffset, this->output_yoffset,
- this->output_width, this->output_height);
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
}
XFlush(this->display);
@@ -937,6 +760,7 @@ static int xv_set_property (vo_driver_t *this_gen,
this->deinterlace_enabled = value;
if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) {
xv_compute_ideal_size (this);
+ xv_compute_output_size (this);
}
break;
case VO_PROP_ASPECT_RATIO:
@@ -947,23 +771,38 @@ static int xv_set_property (vo_driver_t *this_gen,
this->props[property].value = value;
printf("video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n",
this->props[property].value);
-
+ this->sc.user_ratio = value;
+
xv_compute_ideal_size (this);
- xv_compute_output_size (this);
- xv_clean_output_area (this);
-
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
break;
- case VO_PROP_ZOOM_FACTOR:
+ case VO_PROP_ZOOM_X:
- printf ("video_out_xv: VO_PROP_ZOOM %d <=? %d <=? %d\n",
- VO_ZOOM_MIN, value, VO_ZOOM_MAX);
+ if ((value >= VO_ZOOM_MIN) && (value <= VO_ZOOM_MAX)) {
+ this->props[property].value = value;
+ printf ("video_out_xv: VO_PROP_ZOOM_X = %d\n",
+ this->props[property].value);
+
+ this->sc.zoom_factor_x = (double)value / (double)VO_ZOOM_STEP;
+
+ xv_compute_ideal_size (this);
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
+ }
+ break;
+ case VO_PROP_ZOOM_Y:
if ((value >= VO_ZOOM_MIN) && (value <= VO_ZOOM_MAX)) {
this->props[property].value = value;
- printf ("video_out_xv: VO_PROP_ZOOM = %d\n",
+ printf ("video_out_xv: VO_PROP_ZOOM_Y = %d\n",
this->props[property].value);
+
+ this->sc.zoom_factor_y = (double)value / (double)VO_ZOOM_STEP;
xv_compute_ideal_size (this);
+
+ this->sc.force_redraw = 1; /* trigger re-calc of output size */
}
break;
}
@@ -981,34 +820,6 @@ static void xv_get_property_min_max (vo_driver_t *this_gen,
*max = this->props[property].max;
}
-static void xv_translate_gui2video(xv_driver_t *this,
- int x, int y,
- int *vid_x, int *vid_y) {
-
- if (this->output_width > 0 && this->output_height > 0) {
- /*
- * 1.
- * the xv 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 xv 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;
- }
-
- *vid_x = x;
- *vid_y = y;
-}
-
static int xv_gui_data_exchange (vo_driver_t *this_gen,
int data_type, void *data) {
@@ -1034,43 +845,33 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen,
/* FIXME : take care of completion events */
if (this->cur_frame) {
+ int i;
+
XLockDisplay (this->display);
if (this->use_shm) {
XvShmPutImage(this->display, this->xv_port,
this->drawable, this->gc, this->cur_frame->image,
- this->displayed_xoffset, this->displayed_yoffset,
- this->displayed_width, this->displayed_height,
- this->output_xoffset, this->output_yoffset,
- this->output_width, this->output_height, True);
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height, True);
} else {
XvPutImage(this->display, this->xv_port,
this->drawable, this->gc, this->cur_frame->image,
- this->displayed_xoffset, this->displayed_yoffset,
- this->displayed_width, this->displayed_height,
- this->output_xoffset, this->output_yoffset,
- this->output_width, this->output_height);
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height);
}
XSetForeground (this->display, this->gc, this->black.pixel);
- if (this->output_height != this->gui_height) {
- int y = this->output_yoffset + this->output_height;
-
- XFillRectangle(this->display, this->drawable, this->gc, 0, 0,
- this->gui_width, this->output_yoffset);
- XFillRectangle(this->display, this->drawable, this->gc, 0, y,
- this->gui_width, (this->gui_height - y));
- }
- if (this->output_width != this->gui_width) {
- int x = this->output_xoffset + this->output_width;
-
- XFillRectangle(this->display, this->drawable, this->gc,
- 0, this->output_yoffset,
- this->output_xoffset, this->output_height);
- XFillRectangle(this->display, this->drawable, this->gc,
- x, this->output_yoffset,
- this->gui_width - x, this->output_height);
+ for( i = 0; i < 4; i++ ) {
+ if( this->sc.border[i].w && this->sc.border[i].h )
+ XFillRectangle(this->display, this->drawable, this->gc,
+ this->sc.border[i].x, this->sc.border[i].y,
+ this->sc.border[i].w, this->sc.border[i].h);
}
XFlush(this->display);
@@ -1090,9 +891,9 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen,
int x1, y1, x2, y2;
x11_rectangle_t *rect = data;
- xv_translate_gui2video(this, rect->x, rect->y,
+ vo_scale_translate_gui2video(&this->sc, rect->x, rect->y,
&x1, &y1);
- xv_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h,
+ vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h,
&x2, &y2);
rect->x = x1;
rect->y = y1;
@@ -1327,21 +1128,11 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
this->display = visual->display;
this->overlay = NULL;
this->screen = visual->screen;
- this->display_ratio = visual->display_ratio;
- this->frame_output_cb = visual->frame_output_cb;
- this->user_data = visual->user_data;
- this->output_xoffset = 0;
- this->output_yoffset = 0;
- this->output_width = 0;
- this->output_height = 0;
- this->displayed_xoffset = 0;
- this->displayed_yoffset = 0;
- this->displayed_width = 0;
- this->displayed_height = 0;
- this->gui_x = 0;
- this->gui_y = 0;
- this->gui_width = 0;
- this->gui_height = 0;
+
+ vo_scale_init( &this->sc, visual->display_ratio, 1, 0 );
+ this->sc.frame_output_cb = visual->frame_output_cb;
+ this->sc.user_data = visual->user_data;
+
this->drawable = visual->d;
this->gc = XCreateGC (this->display, this->drawable, 0, NULL);
this->xv_port = xv_port;
@@ -1385,8 +1176,9 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
}
this->props[VO_PROP_INTERLACED].value = 0;
- this->props[VO_PROP_ASPECT_RATIO].value = ASPECT_AUTO;
- this->props[VO_PROP_ZOOM_FACTOR].value = 100;
+ this->sc.user_ratio = this->props[VO_PROP_ASPECT_RATIO].value = ASPECT_AUTO;
+ this->props[VO_PROP_ZOOM_X].value = 100;
+ this->props[VO_PROP_ZOOM_Y].value = 100;
/*
* check this adaptor's capabilities
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
+