aspect: add --video-recenter

This ignores --video-align-{x,y} when the video is smaller than the
window in the respective direction.

After zooming in, panning and zooming out, this is useful to recenter
the video in the window.

Unlike doing this by observing osd-dimensions in a script, this is done
before rerendering, so you don't see the image being rendered uncentered
for an instant after zooming out, before being rerendered centered.

Also update --video-align docs while at it.

This doesn't work well with --video-pan-{x,y} because you can move the
output rectangle far away from the image, and when zooming out pan is
abruptly reset to the center. It doesn't feel like natural like zooming
out after changing --video-align-{x,y}. So this commit doesn't set pan
to 0. Also this leaves a way to move scaled images within the window
even with --video-recenter.
This commit is contained in:
Guido Cella
2024-12-02 21:57:20 +01:00
committed by Kacper Michajłow
parent 43f4568816
commit f7e6e30a49
5 changed files with 34 additions and 6 deletions

View File

@@ -0,0 +1 @@
add `--video-recenter` option

View File

@@ -1652,17 +1652,37 @@ Video
``--keepaspect=no`` is used.
``--video-align-x=<-1-1>``, ``--video-align-y=<-1-1>``
Moves the video rectangle within the black borders, which are usually added
to pad the video to screen if video and screen aspect ratios are different.
``--video-align-y=-1`` would move the video to the top of the screen
(leaving a border only on the bottom), a value of ``0`` centers it
(default), and a value of ``1`` would put the video at the bottom of the
screen.
When the video is bigger than the window, these move the displayed rectangle
to show different parts of the video. ``--video-align-y=-1`` would display
the top of the video, ``0`` would display the center (default), and ``1``
would display the bottom.
When the video is smaller than the window and ``--video-recenter`` is
disabled, these move the video rectangle within the black borders, which are
usually added to pad the video to the window if video and window aspect
ratios are different. ``--video-align-y=-1`` would move the video to the top
of the window (leaving a border only on the bottom), ``0`` would center it,
and ``1`` would put the video at the bottom of the window.
If video and screen aspect match perfectly, these options do nothing.
Unlike ``--video-pan-x`` and ``--video-pan-y``, these don't go beyond the
video's or window's boundaries or make the displayed rectangle drift off
after zooming.
This option is disabled if ``--keepaspect=no`` is used.
``--video-recenter=<yes|no>``
Whether to behave as if ``--video-align-x`` and ``--video-align-y`` were 0
when the video becomes smaller than the window in the respective direction
After zooming in until the video is bigger the window, panning with
`--video-align-x` and/or `--video-align-y`, and zooming out until the video
is smaller than the window, this is useful to recenter the video in the
window.
Default: no.
``--video-margin-ratio-left=<val>``, ``--video-margin-ratio-right=<val>``, ``--video-margin-ratio-top=<val>``, ``--video-margin-ratio-bottom=<val>``
Set extra video margins on each border (default: 0). Each value is a ratio
of the window size, using a range 0.0-1.0. For example, setting the option

View File

@@ -165,6 +165,7 @@ static const m_option_t mp_vo_opt_list[] = {
{"video-crop", OPT_RECT(video_crop), .flags = UPDATE_IMGPAR},
{"video-unscaled", OPT_CHOICE(unscaled,
{"no", 0}, {"yes", 1}, {"downscale-big", 2})},
{"video-recenter", OPT_BOOL(recenter)},
{"wid", OPT_INT64(WinID)},
{"screen", OPT_CHOICE(screen_id, {"default", -1}), M_RANGE(0, 32)},
{"screen-name", OPT_STRING(screen_name)},

View File

@@ -58,6 +58,7 @@ typedef struct mp_vo_opts {
double window_scale;
bool auto_window_resize;
bool recenter;
bool keepaspect;
bool keepaspect_window;
bool hidpi_window_scale;

View File

@@ -76,12 +76,15 @@ static void clamp_size(int size, int *start, int *end)
static void src_dst_split_scaling(int src_size, int dst_size,
int scaled_src_size,
float zoom, float align, float pan, float scale,
bool recenter,
int *src_start, int *src_end,
int *dst_start, int *dst_end,
int *osd_margin_a, int *osd_margin_b)
{
scaled_src_size *= powf(2, zoom) * scale;
scaled_src_size = MPMAX(scaled_src_size, 1);
if (recenter && dst_size >= scaled_src_size)
align = 0;
align = (align + 1) / 2;
*dst_start = (dst_size - scaled_src_size) * align + pan * scaled_src_size;
@@ -173,10 +176,12 @@ void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts,
&scaled_width, &scaled_height);
src_dst_split_scaling(src_w, vid_window_w, scaled_width,
opts->zoom, opts->align_x, opts->pan_x, opts->scale_x,
opts->recenter,
&src.x0, &src.x1, &dst.x0, &dst.x1,
&osd.ml, &osd.mr);
src_dst_split_scaling(src_h, vid_window_h, scaled_height,
opts->zoom, opts->align_y, opts->pan_y, opts->scale_y,
opts->recenter,
&src.y0, &src.y1, &dst.y0, &dst.y1,
&osd.mt, &osd.mb);
}