1From 4e301bfe0bafe8fd9b6ca88bae11a8b6f055e41a Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Tue, 30 Mar 2021 07:08:06 +0800 4Subject: [PATCH 21/41] waylandsink: Support window fill-mode property 5 6Tested with: 7gst-launch-1.0 videotestsrc ! waylandsink fullscreen=1 fill-mode=crop 8 9Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 10--- 11 ext/wayland/gstwaylandsink.c | 56 ++++++++++++++++++++++++++++++ 12 ext/wayland/gstwaylandsink.h | 1 + 13 gst-libs/gst/wayland/gstwlwindow.c | 43 ++++++++++++++++++++++- 14 gst-libs/gst/wayland/gstwlwindow.h | 11 ++++++ 15 4 files changed, 110 insertions(+), 1 deletion(-) 16 17diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c 18index 008c774..2c5b295 100644 19--- a/ext/wayland/gstwaylandsink.c 20+++ b/ext/wayland/gstwaylandsink.c 21@@ -63,9 +63,12 @@ enum 22 PROP_ROTATE_METHOD, 23 PROP_LAYER, 24 PROP_ALPHA, 25+ PROP_FILL_MODE, 26 PROP_LAST 27 }; 28 29+static GstWlWindowFillMode DEFAULT_FILL_MODE = GST_WL_WINDOW_FIT; 30+ 31 GST_DEBUG_CATEGORY (gstwayland_debug); 32 #define GST_CAT_DEFAULT gstwayland_debug 33 34@@ -136,6 +139,24 @@ gst_wl_window_layer_get_type (void) 35 return layer; 36 } 37 38+#define GST_TYPE_WL_WINDOW_FILL_MODE (gst_wl_window_fill_mode_get_type ()) 39+static GType 40+gst_wl_window_fill_mode_get_type (void) 41+{ 42+ static GType mode = 0; 43+ 44+ if (!mode) { 45+ static const GEnumValue modes[] = { 46+ {GST_WL_WINDOW_STRETCH, "Ignore aspect ratio", "stretch"}, 47+ {GST_WL_WINDOW_FIT, "Keep aspect ratio", "fit"}, 48+ {GST_WL_WINDOW_CROP, "Keep aspect ratio by expanding", "crop"}, 49+ {0, NULL, NULL} 50+ }; 51+ mode = g_enum_register_static ("GstWlWindowFillMode", modes); 52+ } 53+ return mode; 54+} 55+ 56 static void 57 gst_wayland_sink_class_init (GstWaylandSinkClass * klass) 58 { 59@@ -208,6 +229,15 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass) 60 "Wayland window alpha", 0.0, 1.0, 1.0, 61 G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); 62 63+ if (g_getenv ("WAYLANDSINK_STRETCH")) 64+ DEFAULT_FILL_MODE = GST_WL_WINDOW_STRETCH; 65+ 66+ g_object_class_install_property (gobject_class, PROP_FILL_MODE, 67+ g_param_spec_enum ("fill-mode", "Window fill mode", 68+ "Wayland window fill mode", 69+ GST_TYPE_WL_WINDOW_FILL_MODE, DEFAULT_FILL_MODE, 70+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 71+ 72 /** 73 * waylandsink:render-rectangle: 74 * 75@@ -228,6 +258,7 @@ gst_wayland_sink_init (GstWaylandSink * self) 76 self->window_handle = 1; 77 self->layer = GST_WL_WINDOW_LAYER_NORMAL; 78 self->alpha = 1.0; 79+ self->fill_mode = DEFAULT_FILL_MODE; 80 } 81 82 static void 83@@ -303,6 +334,19 @@ gst_wayland_sink_set_alpha (GstWaylandSink * self, gdouble alpha) 84 g_mutex_unlock (&self->render_lock); 85 } 86 87+static void 88+gst_wayland_sink_set_fill_mode (GstWaylandSink * self, 89+ GstWlWindowFillMode fill_mode) 90+{ 91+ if (fill_mode == self->fill_mode) 92+ return; 93+ 94+ g_mutex_lock (&self->render_lock); 95+ self->fill_mode = fill_mode; 96+ gst_wl_window_ensure_fill_mode (self->window, fill_mode); 97+ g_mutex_unlock (&self->render_lock); 98+} 99+ 100 static void 101 gst_wayland_sink_get_property (GObject * object, 102 guint prop_id, GValue * value, GParamSpec * pspec) 103@@ -335,6 +379,11 @@ gst_wayland_sink_get_property (GObject * object, 104 g_value_set_double (value, self->alpha); 105 GST_OBJECT_UNLOCK (self); 106 break; 107+ case PROP_FILL_MODE: 108+ GST_OBJECT_LOCK (self); 109+ g_value_set_enum (value, self->fill_mode); 110+ GST_OBJECT_UNLOCK (self); 111+ break; 112 default: 113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 114 break; 115@@ -372,6 +421,11 @@ gst_wayland_sink_set_property (GObject * object, 116 gst_wayland_sink_set_alpha (self, g_value_get_double (value)); 117 GST_OBJECT_UNLOCK (self); 118 break; 119+ case PROP_FILL_MODE: 120+ GST_OBJECT_LOCK (self); 121+ gst_wayland_sink_set_fill_mode (self, g_value_get_enum (value)); 122+ GST_OBJECT_UNLOCK (self); 123+ break; 124 default: 125 if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value)) 126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 127@@ -857,6 +911,7 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) 128 gst_wl_window_set_rotate_method (self->window, 129 self->current_rotate_method); 130 gst_wl_window_ensure_alpha (self->window, self->alpha); 131+ gst_wl_window_ensure_fill_mode (self->window, self->fill_mode); 132 } 133 } 134 135@@ -1116,6 +1171,7 @@ gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay, guintptr handle) 136 gst_wl_window_set_rotate_method (self->window, 137 self->current_rotate_method); 138 gst_wl_window_ensure_alpha (self->window, self->alpha); 139+ gst_wl_window_ensure_fill_mode (self->window, self->fill_mode); 140 141 if (self->last_buffer) { 142 /* Resend video info to force resize video surface */ 143diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h 144index 0339ef7..7abfea1 100644 145--- a/ext/wayland/gstwaylandsink.h 146+++ b/ext/wayland/gstwaylandsink.h 147@@ -59,6 +59,7 @@ struct _GstWaylandSink 148 gboolean fullscreen; 149 GstWlWindowLayer layer; 150 gdouble alpha; 151+ GstWlWindowFillMode fill_mode; 152 153 gchar *display_name; 154 155diff --git a/gst-libs/gst/wayland/gstwlwindow.c b/gst-libs/gst/wayland/gstwlwindow.c 156index f470338..7dc0da5 100644 157--- a/gst-libs/gst/wayland/gstwlwindow.c 158+++ b/gst-libs/gst/wayland/gstwlwindow.c 159@@ -71,6 +71,8 @@ typedef struct _GstWlWindowPrivate 160 /* when this is not set both the area_surface and the video_surface are not 161 * visible and certain steps should be skipped */ 162 gboolean is_area_surface_mapped; 163+ 164+ GstWlWindowFillMode fill_mode; 165 } GstWlWindowPrivate; 166 167 G_DEFINE_TYPE_WITH_CODE (GstWlWindow, gst_wl_window, G_TYPE_OBJECT, 168@@ -253,6 +255,19 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock) 169 return self; 170 } 171 172+void 173+gst_wl_window_ensure_fill_mode (GstWlWindow * self, 174+ GstWlWindowFillMode fill_mode) 175+{ 176+ GstWlWindowPrivate *priv; 177+ 178+ if (!self) 179+ return; 180+ 181+ priv = gst_wl_window_get_instance_private (self); 182+ priv->fill_mode = fill_mode; 183+} 184+ 185 static void 186 gst_wl_window_set_config (GstWlWindow * self, const char *config) 187 { 188@@ -510,7 +525,33 @@ gst_wl_window_resize_video_surface (GstWlWindow * self, gboolean commit) 189 190 /* center the video_subsurface inside area_subsurface */ 191 if (priv->video_viewport) { 192- gst_video_center_rect (&src, &dst, &res, TRUE); 193+ if (priv->fill_mode == GST_WL_WINDOW_STRETCH) { 194+ res = dst; 195+ } else if (priv->fill_mode == GST_WL_WINDOW_FIT) { 196+ gst_video_sink_center_rect (src, dst, &res, TRUE); 197+ } else if (priv->fill_mode == GST_WL_WINDOW_CROP) { 198+ gdouble src_ratio, dst_ratio; 199+ 200+ src_ratio = (gdouble) src.w / src.h; 201+ dst_ratio = (gdouble) dst.w / dst.h; 202+ 203+ if (src_ratio < dst_ratio) { 204+ int h = src.w / dst_ratio; 205+ src.y = (src.h - h) / 2; 206+ src.h = h; 207+ } else if (src_ratio > dst_ratio) { 208+ int w = src.h * dst_ratio; 209+ src.x = (src.w - w) / 2; 210+ src.w = w; 211+ } 212+ 213+ wp_viewport_set_source (priv->video_viewport, 214+ wl_fixed_from_int (src.x), wl_fixed_from_int (src.y), 215+ wl_fixed_from_int (src.w), wl_fixed_from_int (src.h)); 216+ 217+ res = dst; 218+ } 219+ 220 wp_viewport_set_destination (priv->video_viewport, res.w, res.h); 221 } else { 222 gst_video_center_rect (&src, &dst, &res, FALSE); 223diff --git a/gst-libs/gst/wayland/gstwlwindow.h b/gst-libs/gst/wayland/gstwlwindow.h 224index 2672e0f..1571ece 100644 225--- a/gst-libs/gst/wayland/gstwlwindow.h 226+++ b/gst-libs/gst/wayland/gstwlwindow.h 227@@ -35,11 +35,22 @@ typedef enum 228 GST_WL_WINDOW_LAYER_BOTTOM = 2, 229 } GstWlWindowLayer; 230 231+typedef enum 232+{ 233+ GST_WL_WINDOW_STRETCH = 0, 234+ GST_WL_WINDOW_FIT = 1, 235+ GST_WL_WINDOW_CROP = 2, 236+} GstWlWindowFillMode; 237+ 238 struct _GstWlWindow 239 { 240 GObject parent_instance; 241 }; 242 243+GST_WL_API 244+void gst_wl_window_ensure_fill_mode (GstWlWindow * self, 245+ GstWlWindowFillMode fill_mode); 246+ 247 GST_WL_API 248 void gst_wl_window_ensure_alpha (GstWlWindow * self, gdouble alpha); 249 250-- 2512.20.1 252 253