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