video: add --autofit and --autofit-larger options

--autofit=WxH sets the window size to a maximum width and/or height,
without changing the window's aspect ratio.

--autofit-larger=WxH does the same, but only if the video size is
actually larger than the window size that would result when using
the --autofit=WxH option with the same arguments.
This commit is contained in:
wm4 2013-01-23 10:56:36 +01:00
parent ccaed5eb07
commit 7885fce7ea
7 changed files with 118 additions and 2 deletions

View File

@ -203,6 +203,51 @@
Enables caching for the stream used by ``--audiofile``, using the
specified amount of memory.
--autofit=<[W[xH]]>
Set the initial window size to a maximum size specified by WxH, without
changing the window's aspect ratio. The size is measured in pixels, or if
a number is followed by a percentage sign (``%``), in percents of the
screen size.
This option never changes the aspect ratio of the window. If the aspect
ratio mismatches, the window's size is reduced until it fits into the
specified size.
Window position is not taken into account, nor is it modified by this
option (the window manager still may place the window differently depending
on size). Use ``--geometry`` to change the window position. Its effects
are applied after this option.
See ``--geometry`` for details how this is handled with multi-monitor
setups, or if the ``--wid`` option is used.
Use ``--autofit-larger`` instead if you don't want the window to get larger.
Use ``--geometry`` if you want to force both window width and height to a
specific size.
*NOTE*: Generally only supported by GUI VOs. Ignored for encoding.
*EXAMPLE*:
``70%``
Make the window width 70% of the screen size, keeping aspect ratio.
``1000``
Set the window width to 1000 pixels, keeping aspect ratio.
``70%:60%``
Make the window as large as possible, without being wider than 70% of
the screen width, or higher than 60% of the screen height.
--autofit-larger=<[W[xH]]>
This option behaves exactly like ``--autofit``, except the window size is
only changed if the window would be larger than the specified size.
*EXAMPLE*:
``90%x80%``
If the video is larger than 90% of the screen width or 80% of the
screen height, make the window smaller until either its width is 90%
of the screen, or its height is 80% of the screen.
--autosub, --no-autosub
Load additional subtitle files matching the video filename. Enabled by
default. See also ``--autosub-match``.
@ -718,6 +763,9 @@
Sets the window to half the screen widths, and positions it 10 pixels
below/left of the top left corner of the screen.
See also ``--autofit`` and ``--autofit-larger`` for fitting the window into
a given size without changing aspect ratio.
--grabpointer, --no-grabpointer
``--no-grabpointer`` tells the player to not grab the mouse pointer after a
video mode change (``--vm``). Useful for multihead setups.

View File

@ -586,6 +586,8 @@ const m_option_t mplayer_opts[]={
OPT_INTRANGE("screenw", vo_screenwidth, CONF_GLOBAL, 0, 4096),
OPT_INTRANGE("screenh", vo_screenheight, CONF_GLOBAL, 0, 4096),
OPT_GEOMETRY("geometry", vo_geometry, 0),
OPT_SIZE_BOX("autofit", vo_autofit, 0),
OPT_SIZE_BOX("autofit-larger", vo_autofit_larger, 0),
OPT_MAKE_FLAGS("force-window-position", force_window_position, 0),
// vo name (X classname) and window title strings
OPT_STRING("name", vo_winname, 0),

View File

@ -1309,7 +1309,34 @@ const m_option_type_t m_option_type_geometry = {
.parse = parse_geometry,
};
static int parse_size_box(const m_option_t *opt, struct bstr name,
struct bstr param, void *dst)
{
struct m_geometry gm;
if (!parse_geometry_str(&gm, param))
goto error;
if (gm.xy_valid)
goto error;
if (dst)
*((struct m_geometry *)dst) = gm;
return 1;
error:
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: invalid size: '%.*s'\n",
BSTR_P(name), BSTR_P(param));
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Valid format: W[%%][xH[%%]] or empty string\n");
return M_OPT_INVALID;
}
const m_option_type_t m_option_type_size_box = {
.name = "Window size",
.size = sizeof(struct m_geometry),
.parse = parse_size_box,
};
#include "video/img_format.h"

View File

@ -57,6 +57,7 @@ extern const m_option_type_t m_option_type_fourcc;
extern const m_option_type_t m_option_type_afmt;
extern const m_option_type_t m_option_type_color;
extern const m_option_type_t m_option_type_geometry;
extern const m_option_type_t m_option_type_size_box;
// Callback used by m_option_type_print_func options.
typedef int (*m_opt_func_full_t)(const m_option_t *, const char *, const char *);
@ -219,6 +220,7 @@ union m_option_value {
struct m_rel_time rel_time;
struct m_color color;
struct m_geometry geometry;
struct m_geometry size_box;
};
////////////////////////////////////////////////////////////////////////////
@ -534,6 +536,7 @@ static inline void m_option_free(const m_option_t *opt, void *dst)
#define OPT_REL_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_rel_time)
#define OPT_COLOR(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_color)
#define OPT_GEOMETRY(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_geometry)
#define OPT_SIZE_BOX(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_size_box)
#define OPT_TRACKCHOICE(name, var) OPT_CHOICE_OR_INT(name, var, 0, 0, 8190, ({"no", -2}, {"auto", -1}))

View File

@ -21,6 +21,8 @@ typedef struct MPOpts {
int vo_screenwidth;
int vo_screenheight;
struct m_geometry vo_geometry;
struct m_geometry vo_autofit;
struct m_geometry vo_autofit_larger;
int force_window_position;
char *vo_winname;
char *vo_wintitle;

View File

@ -28,6 +28,9 @@
# force starting with centered window
#geometry=50%:50%
# don't allow a new window to have a size larger than 90% of the screen size
#autofit-larger=90%x90%
# Keep the player window on top of all other windows.
#ontop=yes

View File

@ -355,6 +355,32 @@ struct vo *init_best_video_out(struct MPOpts *opts,
return NULL;
}
// Fit *w/*h into the size specified by geo.
static void apply_autofit(int *w, int *h, int scr_w, int scr_h,
struct m_geometry *geo, bool allow_upscale)
{
if (!geo->wh_valid)
return;
int dummy;
int n_w = *w, n_h = *h;
m_geometry_apply(&dummy, &dummy, &n_w, &n_h, scr_w, scr_h, geo);
if (!allow_upscale && *w <= n_w && *h <= n_h)
return;
// If aspect mismatches, always make the window smaller than the fit box
double asp = (double)*w / *h;
double n_asp = (double)n_w / n_h;
if (n_asp <= asp) {
*w = n_w;
*h = n_w / asp;
} else {
*w = n_h * asp;
*h = n_h;
}
}
// Set window size (vo->dwidth/dheight) and position (vo->dx/dy) according to
// the video display size d_w/d_h.
// NOTE: currently, all GUI backends do their own handling of window geometry
@ -365,6 +391,9 @@ static void determine_window_geometry(struct vo *vo, int d_w, int d_h)
{
struct MPOpts *opts = vo->opts;
int scr_w = opts->vo_screenwidth;
int scr_h = opts->vo_screenheight;
int vid_w = vo->aspdat.orgw;
int vid_h = vo->aspdat.orgh;
@ -400,10 +429,12 @@ static void determine_window_geometry(struct vo *vo, int d_w, int d_h)
}
}
apply_autofit(&d_w, &d_h, scr_w, scr_h, &opts->vo_autofit, true);
apply_autofit(&d_w, &d_h, scr_w, scr_h, &opts->vo_autofit_larger, false);
vo->dx = (int)(opts->vo_screenwidth - d_w) / 2;
vo->dy = (int)(opts->vo_screenheight - d_h) / 2;
m_geometry_apply(&vo->dx, &vo->dy, &d_w, &d_h,
opts->vo_screenwidth, opts->vo_screenheight,
m_geometry_apply(&vo->dx, &vo->dy, &d_w, &d_h, scr_w, scr_h,
&opts->vo_geometry);
vo->dx += xinerama_x;