1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-17 04:58:06 +00:00

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.
This commit is contained in:
wm4 2012-10-27 22:10:32 +02:00
parent 3466057feb
commit 6f408d0d9d
6 changed files with 169 additions and 187 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,
"<vo_direct3d>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) <gogothebee@gmail.com> and others"

View File

@ -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.

View File

@ -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)

View File

@ -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,