waylandsink: Add force-aspect-ratio property

Similar to and inspired by glimagesink, xvimagesink and others.

The waylandsink never transform the buffer in any way but delegates this to the
Wayland compositor with the Wayland buffer transform API.
Rotation and window size are already supported, so this just changes the video
surface geometry that is communicated to the Wayland compositor.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9210>
This commit is contained in:
Michael Olbrich 2025-06-12 12:45:57 +02:00 committed by GStreamer Marge Bot
parent 9363054e63
commit 31f3e73066
5 changed files with 81 additions and 1 deletions

View File

@ -255902,6 +255902,18 @@
"type": "gchararray",
"writable": true
},
"force-aspect-ratio": {
"blurb": "When enabled, scaling will respect original aspect ratio",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "true",
"mutable": "playing",
"readable": true,
"type": "gboolean",
"writable": true
},
"fullscreen": {
"blurb": "Whether the surface should be made fullscreen ",
"conditionally-available": false,

View File

@ -63,6 +63,7 @@ enum
PROP_FULLSCREEN,
PROP_ROTATE_METHOD,
PROP_DRM_DEVICE,
PROP_FORCE_ASPECT_RATIO,
PROP_LAST
};
@ -184,6 +185,18 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
/**
* waylandsink:force-aspect-ratio:
*
* Since: 1.28
*/
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
"When enabled, scaling will respect original aspect ratio",
TRUE,
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
G_PARAM_STATIC_STRINGS));
/**
* waylandsink:render-rectangle:
@ -201,6 +214,7 @@ gst_wayland_sink_init (GstWaylandSink * self)
{
g_mutex_init (&self->display_lock);
g_mutex_init (&self->render_lock);
self->force_aspect_ratio = TRUE;
}
static void
@ -252,6 +266,23 @@ gst_wayland_sink_set_rotate_method (GstWaylandSink * self,
GST_OBJECT_UNLOCK (self);
}
/* must be called with the OBJECT_LOCK */
static void
gst_wayland_sink_set_force_aspect_ratio (GstWaylandSink * self,
gboolean force_aspect_ratio)
{
if (force_aspect_ratio == self->force_aspect_ratio)
return;
self->force_aspect_ratio = force_aspect_ratio;
if (self->window) {
g_mutex_lock (&self->render_lock);
gst_wl_window_set_force_aspect_ratio (self->window,
self->force_aspect_ratio);
g_mutex_unlock (&self->render_lock);
}
}
static void
gst_wayland_sink_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
@ -279,6 +310,11 @@ gst_wayland_sink_get_property (GObject * object,
g_value_set_string (value, self->drm_device);
GST_OBJECT_UNLOCK (self);
break;
case PROP_FORCE_ASPECT_RATIO:
GST_OBJECT_LOCK (self);
g_value_set_boolean (value, self->force_aspect_ratio);
GST_OBJECT_UNLOCK (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -313,6 +349,12 @@ gst_wayland_sink_set_property (GObject * object,
self->drm_device = g_value_dup_string (value);
GST_OBJECT_UNLOCK (self);
break;
case PROP_FORCE_ASPECT_RATIO:
GST_OBJECT_LOCK (self);
gst_wayland_sink_set_force_aspect_ratio (self,
g_value_get_boolean (value));
GST_OBJECT_UNLOCK (self);
break;
default:
if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -866,6 +908,8 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
G_CALLBACK (on_window_closed), self, 0);
gst_wl_window_set_rotate_method (self->window,
self->current_rotate_method);
gst_wl_window_set_force_aspect_ratio (self->window,
self->force_aspect_ratio);
}
}
@ -1134,6 +1178,8 @@ gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay, guintptr handle)
&self->render_lock);
gst_wl_window_set_rotate_method (self->window,
self->current_rotate_method);
gst_wl_window_set_force_aspect_ratio (self->window,
self->force_aspect_ratio);
}
} else {
GST_ERROR_OBJECT (self, "Failed to find display handle, "

View File

@ -69,6 +69,7 @@ struct _GstWaylandSink
gchar *drm_device;
gboolean skip_dumb_buffer_copy;
gboolean force_aspect_ratio;
};
struct _GstWaylandSinkClass

View File

@ -73,6 +73,8 @@ typedef struct _GstWlWindowPrivate
enum wl_output_transform buffer_transform;
gboolean force_aspect_ratio;
/* when this is not set both the area_surface and the video_surface are not
* visible and certain steps should be skipped */
gboolean is_area_surface_mapped;
@ -257,6 +259,7 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock)
priv->display = g_object_ref (display);
priv->render_lock = render_lock;
g_cond_init (&priv->configure_cond);
priv->force_aspect_ratio = TRUE;
compositor = gst_wl_display_get_compositor (display);
priv->area_surface = wl_compositor_create_surface (compositor);
@ -502,7 +505,10 @@ gst_wl_window_resize_video_surface (GstWlWindow * self, gboolean commit)
/* center the video_subsurface inside area_subsurface */
if (priv->video_viewport) {
gst_video_center_rect (&src, &dst, &res, TRUE);
if (!priv->force_aspect_ratio)
res = dst;
else
gst_video_center_rect (&src, &dst, &res, TRUE);
wp_viewport_set_source (priv->video_viewport, wl_fixed_from_int (0),
wl_fixed_from_int (0), wl_fixed_from_int (wp_src_width),
wl_fixed_from_int (wp_src_height));
@ -1103,3 +1109,14 @@ gst_wl_window_set_colorimetry (GstWlWindow * self,
GST_OBJECT_UNLOCK (self);
}
void
gst_wl_window_set_force_aspect_ratio (GstWlWindow * self,
gboolean force_aspect_ratio)
{
GstWlWindowPrivate *priv = gst_wl_window_get_instance_private (self);
priv->force_aspect_ratio = force_aspect_ratio;
gst_wl_window_update_geometry (self);
}

View File

@ -74,4 +74,8 @@ GST_WL_API
void gst_wl_window_set_rotate_method (GstWlWindow *self,
GstVideoOrientationMethod rotate_method);
GST_WL_API
void gst_wl_window_set_force_aspect_ratio (GstWlWindow * self,
gboolean force_aspect_ratio);
G_END_DECLS