From 6f408d0d9d6d0655faec75474bc3074812b41826 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 27 Oct 2012 22:10:32 +0200 Subject: [PATCH] VO: remove code duplication for setting up mp_osd_res vo_opengl, vo_vdpau, vo_direct3d had the code for setting up mp_osd_res duplicated. Make things simpler by making calc_src_dst_rects() setup the full mp_osd_res structure, instead of just "borders". Also, rename that function to vo_get_src_dst_rects(), and make it use mp_rect. Remove vo_rect, which was annoying because it contains redundant members (width/height additional to right/bottom). Add code to print the video rect etc. in verbose mode. There should be no actual change how the video rects are calculated. The only exception are the bottom/right subtitle margins, which are now computed slightly differently, but that shouldn't matter. --- libvo/video_out.c | 148 ++++++++++++++++++++++++-------------------- libvo/video_out.h | 13 ++-- libvo/vo_direct3d.c | 43 +++++-------- libvo/vo_opengl.c | 70 +++++++++------------ libvo/vo_vdpau.c | 41 ++++-------- libvo/vo_xv.c | 41 +++++++----- 6 files changed, 169 insertions(+), 187 deletions(-) diff --git a/libvo/video_out.c b/libvo/video_out.c index c16968574d..59600e5ad6 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -39,6 +39,7 @@ #include "m_config.h" #include "mp_msg.h" #include "libmpcodecs/vfcap.h" +#include "sub/sub.h" #include "osdep/shmem.h" #ifdef CONFIG_X11 @@ -416,76 +417,91 @@ int lookup_keymap_table(const struct mp_keymap *map, int key) { return map->to; } -/** - * \brief helper function for the kind of panscan-scaling that needs a source - * and destination rectangle like Direct3D and VDPAU - */ -static void src_dst_split_scaling(int src_size, int dst_size, int scaled_src_size, - int *src_start, int *src_end, int *dst_start, int *dst_end) { - if (scaled_src_size > dst_size) { - int border = src_size * (scaled_src_size - dst_size) / scaled_src_size; - // round to a multiple of 2, this is at least needed for vo_direct3d and ATI cards - border = (border / 2 + 1) & ~1; - *src_start = border; - *src_end = src_size - border; - *dst_start = 0; - *dst_end = dst_size; - } else { - *src_start = 0; - *src_end = src_size; - *dst_start = (dst_size - scaled_src_size) / 2; - *dst_end = *dst_start + scaled_src_size; - } +static void print_video_rect(struct vo *vo, struct mp_rect src, + struct mp_rect dst, struct mp_osd_res osd) +{ + int lv = MSGL_V; + + int sw = src.x1 - src.x0, sh = src.y1 - src.y0; + int dw = dst.x1 - dst.x0, dh = dst.y1 - dst.y0; + + mp_msg(MSGT_VO, lv, "[vo] Window size: %dx%d\n", + vo->dwidth, vo->dheight); + mp_msg(MSGT_VO, lv, "[vo] Video source: %dx%d (%dx%d)\n", + vo->aspdat.orgw, vo->aspdat.orgh, + vo->aspdat.prew, vo->aspdat.preh); + mp_msg(MSGT_VO, lv, "[vo] Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n", + src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh); + mp_msg(MSGT_VO, lv, "[vo] Video scale: %f/%f\n", + (double)dw / sw, (double)dh / sh); + mp_msg(MSGT_VO, lv, "[vo] OSD borders: l=%d t=%d r=%d b=%d\n", + osd.ml, osd.mt, osd.mr, osd.mb); + mp_msg(MSGT_VO, lv, "[vo] Video borders: l=%d t=%d r=%d b=%d\n", + dst.x0, dst.y0, vo->dwidth - dst.x1, vo->dheight - dst.y1); } -/** - * Calculate the appropriate source and destination rectangle to - * get a correctly scaled picture, including pan-scan. - * Can be extended to take future cropping support into account. - * - * \param crop specifies the cropping border size in the left, right, top and bottom members, may be NULL - * \param borders the border values as e.g. EOSD (ASS) and properly placed DVD highlight support requires, - * may be NULL and only left and top are currently valid. - */ -void calc_src_dst_rects(struct vo *vo, int src_width, int src_height, - struct vo_rect *src, struct vo_rect *dst, - struct vo_rect *borders, const struct vo_rect *crop) +static void src_dst_split_scaling(int src_size, int dst_size, + int scaled_src_size, int *src_start, + int *src_end, int *dst_start, int *dst_end) { - static const struct vo_rect no_crop = {0, 0, 0, 0, 0, 0}; - int scaled_width = 0; - int scaled_height = 0; - if (!crop) crop = &no_crop; - src_width -= crop->left + crop->right; - src_height -= crop->top + crop->bottom; - if (src_width < 2) src_width = 2; - if (src_height < 2) src_height = 2; - dst->left = 0; dst->right = vo->dwidth; - dst->top = 0; dst->bottom = vo->dheight; - src->left = 0; src->right = src_width; - src->top = 0; src->bottom = src_height; - if (borders) { - borders->left = 0; borders->top = 0; - } - if (aspect_scaling()) { - aspect(vo, &scaled_width, &scaled_height, A_WINZOOM); - panscan_calc_windowed(vo); - scaled_width += vo->panscan_x; - scaled_height += vo->panscan_y; - if (borders) { - borders->left = (vo->dwidth - scaled_width ) / 2; - borders->top = (vo->dheight - scaled_height) / 2; + if (scaled_src_size > dst_size) { + int border = src_size * (scaled_src_size - dst_size) / scaled_src_size; + // round to a multiple of 2, this is at least needed for vo_direct3d + // and ATI cards + border = (border / 2 + 1) & ~1; + *src_start = border; + *src_end = src_size - border; + *dst_start = 0; + *dst_end = dst_size; + } else { + *src_start = 0; + *src_end = src_size; + *dst_start = (dst_size - scaled_src_size) / 2; + *dst_end = *dst_start + scaled_src_size; } - src_dst_split_scaling(src_width, vo->dwidth, scaled_width, - &src->left, &src->right, &dst->left, &dst->right); - src_dst_split_scaling(src_height, vo->dheight, scaled_height, - &src->top, &src->bottom, &dst->top, &dst->bottom); - } - src->left += crop->left; src->right += crop->left; - src->top += crop->top; src->bottom += crop->top; - src->width = src->right - src->left; - src->height = src->bottom - src->top; - dst->width = dst->right - dst->left; - dst->height = dst->bottom - dst->top; +} + +// Calculate the appropriate source and destination rectangle to +// get a correctly scaled picture, including pan-scan. +// out_src: visible part of the video +// out_dst: area of screen covered by the video source rectangle +// out_osd: OSD size, OSD margins, etc. +void vo_get_src_dst_rects(struct vo *vo, struct mp_rect *out_src, + struct mp_rect *out_dst, struct mp_osd_res *out_osd) +{ + int src_w = vo->aspdat.orgw; + int src_h = vo->aspdat.orgh; + struct mp_rect dst = {0, 0, vo->dwidth, vo->dheight}; + struct mp_rect src = {0, 0, src_w, src_h}; + struct mp_osd_res osd = { + .w = vo->dwidth, + .h = vo->dheight, + .display_par = vo->monitor_par, + .video_par = vo->aspdat.par, + }; + if (aspect_scaling()) { + int scaled_width = 0, scaled_height = 0; + aspect(vo, &scaled_width, &scaled_height, A_WINZOOM); + panscan_calc_windowed(vo); + scaled_width += vo->panscan_x; + scaled_height += vo->panscan_y; + int border_w = vo->dwidth - scaled_width; + int border_h = vo->dheight - scaled_height; + osd.ml = border_w / 2; + osd.mt = border_h / 2; + osd.mr = border_w - osd.ml; + osd.mb = border_h - osd.mt; + src_dst_split_scaling(src_w, vo->dwidth, scaled_width, + &src.x0, &src.x1, &dst.x0, &dst.x1); + src_dst_split_scaling(src_h, vo->dheight, scaled_height, + &src.y0, &src.y1, &dst.y0, &dst.y1); + } + + *out_src = src; + *out_dst = dst; + *out_osd = osd; + + print_video_rect(vo, src, dst, osd); } // Return the window title the VO should set. Always returns a null terminated diff --git a/libvo/video_out.h b/libvo/video_out.h index 5c8e10a008..4ea4144ffc 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -257,7 +257,7 @@ struct vo { int event_fd; // check_events() should be called when this has input int registered_fd; // set to event_fd when registered in input system - // requested position/resolution + // requested position/resolution (usually window position/window size) int dx; int dy; int dwidth; @@ -338,14 +338,13 @@ struct mp_keymap { int to; }; int lookup_keymap_table(const struct mp_keymap *map, int key); -struct vo_rect { - int left, right, top, bottom, width, height; -}; -void calc_src_dst_rects(struct vo *vo, int src_width, int src_height, - struct vo_rect *src, struct vo_rect *dst, - struct vo_rect *borders, const struct vo_rect *crop); + void vo_mouse_movement(struct vo *vo, int posx, int posy); +struct mp_osd_res; +void vo_get_src_dst_rects(struct vo *vo, struct mp_rect *out_src, + struct mp_rect *out_dst, struct mp_osd_res *out_osd); + static inline int aspect_scaling(void) { return vo_keepaspect || vo_fs; diff --git a/libvo/vo_direct3d.c b/libvo/vo_direct3d.c index 5fc2a64893..294a101ffe 100644 --- a/libvo/vo_direct3d.c +++ b/libvo/vo_direct3d.c @@ -145,8 +145,7 @@ typedef struct d3d_priv { fullscreen */ int src_width; /**< Source (movie) width */ int src_height; /**< Source (movie) heigth */ - int border_x; /**< horizontal border value for OSD */ - int border_y; /**< vertical border value for OSD */ + struct mp_osd_res osd_res; int image_format; /**< mplayer image format */ bool use_textures; /**< use 3D texture rendering, instead of StretchRect */ @@ -294,22 +293,18 @@ static bool d3d_begin_scene(d3d_priv *priv) */ static void calc_fs_rect(d3d_priv *priv) { - struct vo_rect src_rect; - struct vo_rect dst_rect; - struct vo_rect borders; - calc_src_dst_rects(priv->vo, priv->src_width, priv->src_height, &src_rect, - &dst_rect, &borders, NULL); + struct mp_rect src_rect; + struct mp_rect dst_rect; + vo_get_src_dst_rects(priv->vo, &src_rect, &dst_rect, &priv->osd_res); - priv->fs_movie_rect.left = dst_rect.left; - priv->fs_movie_rect.right = dst_rect.right; - priv->fs_movie_rect.top = dst_rect.top; - priv->fs_movie_rect.bottom = dst_rect.bottom; - priv->fs_panscan_rect.left = src_rect.left; - priv->fs_panscan_rect.right = src_rect.right; - priv->fs_panscan_rect.top = src_rect.top; - priv->fs_panscan_rect.bottom = src_rect.bottom; - priv->border_x = borders.left; - priv->border_y = borders.top; + priv->fs_movie_rect.left = dst_rect.x0; + priv->fs_movie_rect.right = dst_rect.x1; + priv->fs_movie_rect.top = dst_rect.y0; + priv->fs_movie_rect.bottom = dst_rect.y1; + priv->fs_panscan_rect.left = src_rect.x0; + priv->fs_panscan_rect.right = src_rect.x1; + priv->fs_panscan_rect.top = src_rect.y0; + priv->fs_panscan_rect.bottom = src_rect.y1; mp_msg(MSGT_VO, MSGL_V, "Video rectangle: t: %ld, l: %ld, r: %ld, b:%ld\n", @@ -2063,18 +2058,8 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) if (!priv->d3d_device) return; - struct mp_osd_res res = { - .w = vo->dwidth, - .h = vo->dheight, - .ml = priv->border_x, - .mr = priv->border_x, - .mt = priv->border_y, - .mb = priv->border_y, - .display_par = vo->monitor_par, - .video_par = vo->aspdat.par, - }; - - osd_draw(osd, res, osd->vo_pts, 0, osd_fmt_supported, draw_osd_cb, priv); + osd_draw(osd, priv->osd_res, osd->vo_pts, 0, osd_fmt_supported, + draw_osd_cb, priv); } #define AUTHOR "Georgi Petrov (gogothebee) and others" diff --git a/libvo/vo_opengl.c b/libvo/vo_opengl.c index eef7405561..261e1b102f 100644 --- a/libvo/vo_opengl.c +++ b/libvo/vo_opengl.c @@ -219,9 +219,9 @@ struct gl_priv { int mpi_flipped; int vo_flipped; - struct vo_rect src_rect; // displayed part of the source video - struct vo_rect dst_rect; // video rectangle on output window - int border_x, border_y; // OSD borders + struct mp_rect src_rect; // displayed part of the source video + struct mp_rect dst_rect; // video rectangle on output window + struct mp_osd_res osd_rect; // OSD size/margins int vp_x, vp_y, vp_w, vp_h; // GL viewport int frames_rendered; @@ -790,8 +790,10 @@ static void delete_shaders(struct gl_priv *p) static double get_scale_factor(struct gl_priv *p) { - double sx = p->dst_rect.width / (double)p->src_rect.width; - double sy = p->dst_rect.height / (double)p->src_rect.height; + double sx = (p->dst_rect.x1 - p->dst_rect.x0) / + (double)(p->src_rect.x1 - p->src_rect.x0); + double sy = (p->dst_rect.y1 - p->dst_rect.y0) / + (double)(p->src_rect.y1 - p->src_rect.y0); // xxx: actually we should use different scalers in X/Y directions if the // scale factors are different due to anamorphic content return FFMIN(sx, sy); @@ -1126,16 +1128,16 @@ static void do_render(struct gl_priv *p) gl->Enable(GL_FRAMEBUFFER_SRGB); if (p->stereo_mode) { - int w = p->src_rect.width; + int w = p->src_rect.x1 - p->src_rect.x0; int imgw = p->image_width; glEnable3DLeft(gl, p->stereo_mode); write_quad(vb, - p->dst_rect.left, p->dst_rect.top, - p->dst_rect.right, p->dst_rect.bottom, - p->src_rect.left / 2, p->src_rect.top, - p->src_rect.left / 2 + w / 2, p->src_rect.bottom, + p->dst_rect.x0, p->dst_rect.y0, + p->dst_rect.x1, p->dst_rect.y1, + p->src_rect.x0 / 2, p->src_rect.y0, + p->src_rect.x0 / 2 + w / 2, p->src_rect.y1, final_texw, final_texh, NULL, is_flipped); draw_triangles(p, vb, VERTICES_PER_QUAD); @@ -1143,10 +1145,10 @@ static void do_render(struct gl_priv *p) glEnable3DRight(gl, p->stereo_mode); write_quad(vb, - p->dst_rect.left, p->dst_rect.top, - p->dst_rect.right, p->dst_rect.bottom, - p->src_rect.left / 2 + imgw / 2, p->src_rect.top, - p->src_rect.left / 2 + imgw / 2 + w / 2, p->src_rect.bottom, + p->dst_rect.x0, p->dst_rect.y0, + p->dst_rect.x1, p->dst_rect.y1, + p->src_rect.x0 / 2 + imgw / 2, p->src_rect.y0, + p->src_rect.x0 / 2 + imgw / 2 + w / 2, p->src_rect.y1, final_texw, final_texh, NULL, is_flipped); draw_triangles(p, vb, VERTICES_PER_QUAD); @@ -1154,10 +1156,10 @@ static void do_render(struct gl_priv *p) glDisable3D(gl, p->stereo_mode); } else { write_quad(vb, - p->dst_rect.left, p->dst_rect.top, - p->dst_rect.right, p->dst_rect.bottom, - p->src_rect.left, p->src_rect.top, - p->src_rect.right, p->src_rect.bottom, + p->dst_rect.x0, p->dst_rect.y0, + p->dst_rect.x1, p->dst_rect.y1, + p->src_rect.x0, p->src_rect.y0, + p->src_rect.x1, p->src_rect.y1, final_texw, final_texh, NULL, is_flipped); draw_triangles(p, vb, VERTICES_PER_QUAD); @@ -1174,15 +1176,16 @@ static void do_render(struct gl_priv *p) static void update_window_sized_objects(struct gl_priv *p) { if (p->scale_sep_program) { - if (p->dst_rect.height > p->scale_sep_fbo.tex_h) { + int h = p->dst_rect.y1 - p->dst_rect.y0; + if (h > p->scale_sep_fbo.tex_h) { fbotex_uninit(p, &p->scale_sep_fbo); // Round up to an arbitrary alignment to make window resizing or // panscan controls smoother (less texture reallocations). - int height = FFALIGN(p->dst_rect.height, 256); + int height = FFALIGN(h, 256); fbotex_init(p, &p->scale_sep_fbo, p->image_width, height); } p->scale_sep_fbo.vp_w = p->image_width; - p->scale_sep_fbo.vp_h = p->dst_rect.height; + p->scale_sep_fbo.vp_h = h; } } @@ -1196,11 +1199,7 @@ static void resize(struct gl_priv *p) p->vp_w = vo->dwidth, p->vp_h = vo->dheight; gl->Viewport(p->vp_x, p->vp_y, p->vp_w, p->vp_h); - struct vo_rect borders; - calc_src_dst_rects(vo, p->image_width, p->image_height, &p->src_rect, - &p->dst_rect, &borders, NULL); - p->border_x = borders.left; - p->border_y = borders.top; + vo_get_src_dst_rects(vo, &p->src_rect, &p->dst_rect, &p->osd_rect); bool need_scaler_reinit = false; // filter size change needed bool need_scaler_update = false; // filter LUT change needed @@ -1242,9 +1241,9 @@ static void flip_page(struct vo *vo) p->glctx->swapGlBuffers(p->glctx); - if (p->dst_rect.left > p->vp_x || p->dst_rect.top > p->vp_y - || p->dst_rect.right < p->vp_x + p->vp_w - || p->dst_rect.bottom < p->vp_y + p->vp_h) + if (p->dst_rect.x0 > p->vp_x || p->dst_rect.y0 > p->vp_y + || p->dst_rect.x1 < p->vp_x + p->vp_w + || p->dst_rect.y1 < p->vp_y + p->vp_h) { gl->Clear(GL_COLOR_BUFFER_BIT); } @@ -1449,18 +1448,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) struct gl_priv *p = vo->priv; assert(p->osd); - struct mp_osd_res res = { - .w = vo->dwidth, - .h = vo->dheight, - .ml = p->border_x, - .mr = p->border_x, - .mt = p->border_y, - .mb = p->border_y, - .display_par = vo->monitor_par, - .video_par = vo->aspdat.par, - }; - - osd_draw(osd, res, osd->vo_pts, 0, p->osd->formats, draw_osd_cb, p); + osd_draw(osd, p->osd_rect, osd->vo_pts, 0, p->osd->formats, draw_osd_cb, p); } // Disable features that are not supported with the current OpenGL version. diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index dcd6bb321d..90c438e76f 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -137,7 +137,7 @@ struct vdpctx { VdpRect src_rect_vid; VdpRect out_rect_vid; - int border_x, border_y; + struct mp_osd_res osd_rect; struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES]; int surface_num; @@ -370,21 +370,17 @@ static void resize(struct vo *vo) struct vdpctx *vc = vo->priv; struct vdp_functions *vdp = vc->vdp; VdpStatus vdp_st; - struct vo_rect src_rect; - struct vo_rect dst_rect; - struct vo_rect borders; - calc_src_dst_rects(vo, vc->vid_width, vc->vid_height, &src_rect, &dst_rect, - &borders, NULL); - vc->out_rect_vid.x0 = dst_rect.left; - vc->out_rect_vid.x1 = dst_rect.right; - vc->out_rect_vid.y0 = dst_rect.top; - vc->out_rect_vid.y1 = dst_rect.bottom; - vc->src_rect_vid.x0 = src_rect.left; - vc->src_rect_vid.x1 = src_rect.right; - vc->src_rect_vid.y0 = vc->flip ? src_rect.bottom : src_rect.top; - vc->src_rect_vid.y1 = vc->flip ? src_rect.top : src_rect.bottom; - vc->border_x = borders.left; - vc->border_y = borders.top; + struct mp_rect src_rect; + struct mp_rect dst_rect; + vo_get_src_dst_rects(vo, &src_rect, &dst_rect, &vc->osd_rect); + vc->out_rect_vid.x0 = dst_rect.x0; + vc->out_rect_vid.x1 = dst_rect.x1; + vc->out_rect_vid.y0 = dst_rect.y0; + vc->out_rect_vid.y1 = dst_rect.y1; + vc->src_rect_vid.x0 = src_rect.x0; + vc->src_rect_vid.x1 = src_rect.x1; + vc->src_rect_vid.y0 = vc->flip ? src_rect.y1 : src_rect.y0; + vc->src_rect_vid.y1 = vc->flip ? src_rect.y0 : src_rect.y1; int flip_offset_ms = vo_fs ? vc->flip_offset_fs : vc->flip_offset_window; vo->flip_queue_offset = flip_offset_ms / 1000.; @@ -1119,18 +1115,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) [SUBBITMAP_RGBA] = true, }; - struct mp_osd_res res = { - .w = vo->dwidth, - .h = vo->dheight, - .ml = vc->border_x, - .mr = vc->border_x, - .mt = vc->border_y, - .mb = vc->border_y, - .display_par = vo->monitor_par, - .video_par = vo->aspdat.par, - }; - - osd_draw(osd, res, osd->vo_pts, 0, formats, draw_osd_cb, vo); + osd_draw(osd, vc->osd_rect, osd->vo_pts, 0, formats, draw_osd_cb, vo); } static int update_presentation_queue_status(struct vo *vo) diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c index 90eda230b8..de14f039f4 100644 --- a/libvo/vo_xv.c +++ b/libvo/vo_xv.c @@ -77,8 +77,8 @@ struct xvctx { uint32_t image_height; uint32_t image_format; int is_paused; - struct vo_rect src_rect; - struct vo_rect dst_rect; + struct mp_rect src_rect; + struct mp_rect dst_rect; uint32_t max_width, max_height; // zero means: not set int mode_switched; #ifdef HAVE_SHM @@ -94,11 +94,16 @@ static void resize(struct vo *vo) { struct xvctx *ctx = vo->priv; - calc_src_dst_rects(vo, ctx->image_width, ctx->image_height, &ctx->src_rect, - &ctx->dst_rect, NULL, NULL); - struct vo_rect *dst = &ctx->dst_rect; - vo_x11_clearwindow_part(vo, vo->x11->window, dst->width, dst->height); - vo_xv_draw_colorkey(vo, dst->left, dst->top, dst->width, dst->height); + // Can't be used, because the function calculates screen-space coordinates, + // while we need video-space. + struct mp_osd_res unused; + + vo_get_src_dst_rects(vo, &ctx->src_rect, &ctx->dst_rect, &unused); + + struct mp_rect *dst = &ctx->dst_rect; + int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0; + vo_x11_clearwindow_part(vo, vo->x11->window, dw, dh); + vo_xv_draw_colorkey(vo, dst->x0, dst->y0, dw, dh); } /* @@ -275,20 +280,22 @@ static inline void put_xvimage(struct vo *vo, XvImage *xvi) { struct xvctx *ctx = vo->priv; struct vo_x11_state *x11 = vo->x11; - struct vo_rect *src = &ctx->src_rect; - struct vo_rect *dst = &ctx->dst_rect; + struct mp_rect *src = &ctx->src_rect; + struct mp_rect *dst = &ctx->dst_rect; + int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0; + int sw = src->x1 - src->x0, sh = src->y1 - src->y0; #ifdef HAVE_SHM if (ctx->Shmem_Flag) { XvShmPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi, - src->left, src->top, src->width, src->height, - dst->left, dst->top, dst->width, dst->height, + src->x0, src->y0, sw, sh, + dst->x0, dst->y0, dw, dh, False); } else #endif { XvPutImage(x11->display, x11->xv_port, x11->window, x11->vo_gc, xvi, - src->left, src->top, src->width, src->height, - dst->left, dst->top, dst->width, dst->height); + src->x0, src->y0, sw, sh, + dst->x0, dst->y0, dw, dh); } } @@ -340,9 +347,11 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) struct mp_image img = get_xv_buffer(vo, ctx->current_buf); - struct vo_rect *src = &ctx->src_rect; - struct vo_rect *dst = &ctx->dst_rect; - double xvpar = (double)dst->width / dst->height * src->height / src->width; + struct mp_rect *src = &ctx->src_rect; + struct mp_rect *dst = &ctx->dst_rect; + int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0; + int sw = src->x1 - src->x0, sh = src->y1 - src->y0; + double xvpar = (double)dw / dh * sh / sw; struct mp_osd_res res = { .w = ctx->image_width,