1*4882a593SmuzhiyunFrom 3241f7b42c92410f9d667ed26e5f65dbcb8b2c92 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 20/33] 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 | 55 ++++++++++++++++++++++++++++++++++++ 12*4882a593Smuzhiyun ext/wayland/gstwaylandsink.h | 1 + 13*4882a593Smuzhiyun ext/wayland/wlwindow.c | 28 +++++++++++++++++- 14*4882a593Smuzhiyun ext/wayland/wlwindow.h | 9 ++++++ 15*4882a593Smuzhiyun 4 files changed, 92 insertions(+), 1 deletion(-) 16*4882a593Smuzhiyun 17*4882a593Smuzhiyundiff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c 18*4882a593Smuzhiyunindex ff79ddf..24fd7bd 100644 19*4882a593Smuzhiyun--- a/ext/wayland/gstwaylandsink.c 20*4882a593Smuzhiyun+++ b/ext/wayland/gstwaylandsink.c 21*4882a593Smuzhiyun@@ -66,9 +66,12 @@ enum 22*4882a593Smuzhiyun PROP_FULLSCREEN, 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@@ -185,6 +188,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@@ -244,6 +265,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 gst_video_overlay_install_properties (gobject_class, PROP_LAST); 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun gst_type_mark_as_plugin_api (GST_TYPE_WAYLAND_VIDEO, 0); 75*4882a593Smuzhiyun@@ -258,6 +288,7 @@ gst_wayland_sink_init (GstWaylandSink * sink) 76*4882a593Smuzhiyun sink->window_handle = 1; 77*4882a593Smuzhiyun sink->layer = GST_WL_WINDOW_LAYER_NORMAL; 78*4882a593Smuzhiyun sink->alpha = 1.0; 79*4882a593Smuzhiyun+ sink->fill_mode = DEFAULT_FILL_MODE; 80*4882a593Smuzhiyun } 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun static void 83*4882a593Smuzhiyun@@ -296,6 +327,19 @@ gst_wayland_sink_set_alpha (GstWaylandSink * sink, gdouble alpha) 84*4882a593Smuzhiyun g_mutex_unlock (&sink->render_lock); 85*4882a593Smuzhiyun } 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun+static void 88*4882a593Smuzhiyun+gst_wayland_sink_set_fill_mode (GstWaylandSink * sink, 89*4882a593Smuzhiyun+ GstWlWindowFillMode fill_mode) 90*4882a593Smuzhiyun+{ 91*4882a593Smuzhiyun+ if (fill_mode == sink->fill_mode) 92*4882a593Smuzhiyun+ return; 93*4882a593Smuzhiyun+ 94*4882a593Smuzhiyun+ g_mutex_lock (&sink->render_lock); 95*4882a593Smuzhiyun+ sink->fill_mode = fill_mode; 96*4882a593Smuzhiyun+ sink->resend_info = FALSE; 97*4882a593Smuzhiyun+ g_mutex_unlock (&sink->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@@ -323,6 +367,11 @@ gst_wayland_sink_get_property (GObject * object, 104*4882a593Smuzhiyun g_value_set_double (value, sink->alpha); 105*4882a593Smuzhiyun GST_OBJECT_UNLOCK (sink); 106*4882a593Smuzhiyun break; 107*4882a593Smuzhiyun+ case PROP_FILL_MODE: 108*4882a593Smuzhiyun+ GST_OBJECT_LOCK (sink); 109*4882a593Smuzhiyun+ g_value_set_enum (value, sink->fill_mode); 110*4882a593Smuzhiyun+ GST_OBJECT_UNLOCK (sink); 111*4882a593Smuzhiyun+ break; 112*4882a593Smuzhiyun default: 113*4882a593Smuzhiyun G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 114*4882a593Smuzhiyun break; 115*4882a593Smuzhiyun@@ -356,6 +405,11 @@ gst_wayland_sink_set_property (GObject * object, 116*4882a593Smuzhiyun gst_wayland_sink_set_alpha (sink, g_value_get_double (value)); 117*4882a593Smuzhiyun GST_OBJECT_UNLOCK (sink); 118*4882a593Smuzhiyun break; 119*4882a593Smuzhiyun+ case PROP_FILL_MODE: 120*4882a593Smuzhiyun+ GST_OBJECT_LOCK (sink); 121*4882a593Smuzhiyun+ gst_wayland_sink_set_fill_mode (sink, g_value_get_enum (value)); 122*4882a593Smuzhiyun+ GST_OBJECT_UNLOCK (sink); 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@@ -763,6 +817,7 @@ render_last_buffer (GstWaylandSink * sink, gboolean redraw) 128*4882a593Smuzhiyun sink->video_info_changed = FALSE; 129*4882a593Smuzhiyun sink->resend_info = FALSE; 130*4882a593Smuzhiyun } 131*4882a593Smuzhiyun+ sink->window->fill_mode = sink->fill_mode; 132*4882a593Smuzhiyun gst_wl_window_render (sink->window, wlbuffer, info); 133*4882a593Smuzhiyun } 134*4882a593Smuzhiyun 135*4882a593Smuzhiyundiff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h 136*4882a593Smuzhiyunindex f798969..6fd77e8 100644 137*4882a593Smuzhiyun--- a/ext/wayland/gstwaylandsink.h 138*4882a593Smuzhiyun+++ b/ext/wayland/gstwaylandsink.h 139*4882a593Smuzhiyun@@ -64,6 +64,7 @@ struct _GstWaylandSink 140*4882a593Smuzhiyun gboolean fullscreen; 141*4882a593Smuzhiyun GstWlWindowLayer layer; 142*4882a593Smuzhiyun gdouble alpha; 143*4882a593Smuzhiyun+ GstWlWindowFillMode fill_mode; 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun gchar *display_name; 146*4882a593Smuzhiyun 147*4882a593Smuzhiyundiff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c 148*4882a593Smuzhiyunindex 58e65dd..f4e7ca9 100644 149*4882a593Smuzhiyun--- a/ext/wayland/wlwindow.c 150*4882a593Smuzhiyun+++ b/ext/wayland/wlwindow.c 151*4882a593Smuzhiyun@@ -467,7 +467,33 @@ gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit) 152*4882a593Smuzhiyun dst.h = window->render_rectangle.h; 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun if (window->video_viewport) { 155*4882a593Smuzhiyun- gst_video_sink_center_rect (src, dst, &res, TRUE); 156*4882a593Smuzhiyun+ if (window->fill_mode == GST_WL_WINDOW_STRETCH) { 157*4882a593Smuzhiyun+ res = dst; 158*4882a593Smuzhiyun+ } else if (window->fill_mode == GST_WL_WINDOW_FIT) { 159*4882a593Smuzhiyun+ gst_video_sink_center_rect (src, dst, &res, TRUE); 160*4882a593Smuzhiyun+ } else if (window->fill_mode == GST_WL_WINDOW_CROP) { 161*4882a593Smuzhiyun+ gdouble src_ratio, dst_ratio; 162*4882a593Smuzhiyun+ 163*4882a593Smuzhiyun+ src_ratio = (gdouble) src.w / src.h; 164*4882a593Smuzhiyun+ dst_ratio = (gdouble) dst.w / dst.h; 165*4882a593Smuzhiyun+ 166*4882a593Smuzhiyun+ if (src_ratio < dst_ratio) { 167*4882a593Smuzhiyun+ int h = src.w / dst_ratio; 168*4882a593Smuzhiyun+ src.y = (src.h - h) / 2; 169*4882a593Smuzhiyun+ src.h = h; 170*4882a593Smuzhiyun+ } else if (src_ratio > dst_ratio) { 171*4882a593Smuzhiyun+ int w = src.h * dst_ratio; 172*4882a593Smuzhiyun+ src.x = (src.w - w) / 2; 173*4882a593Smuzhiyun+ src.w = w; 174*4882a593Smuzhiyun+ } 175*4882a593Smuzhiyun+ 176*4882a593Smuzhiyun+ wp_viewport_set_source (window->video_viewport, 177*4882a593Smuzhiyun+ wl_fixed_from_int (src.x), wl_fixed_from_int (src.y), 178*4882a593Smuzhiyun+ wl_fixed_from_int (src.w), wl_fixed_from_int (src.h)); 179*4882a593Smuzhiyun+ 180*4882a593Smuzhiyun+ res = dst; 181*4882a593Smuzhiyun+ } 182*4882a593Smuzhiyun+ 183*4882a593Smuzhiyun wp_viewport_set_destination (window->video_viewport, res.w, res.h); 184*4882a593Smuzhiyun } else { 185*4882a593Smuzhiyun gst_video_sink_center_rect (src, dst, &res, FALSE); 186*4882a593Smuzhiyundiff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h 187*4882a593Smuzhiyunindex 6fb8285..35d9d3c 100644 188*4882a593Smuzhiyun--- a/ext/wayland/wlwindow.h 189*4882a593Smuzhiyun+++ b/ext/wayland/wlwindow.h 190*4882a593Smuzhiyun@@ -37,6 +37,13 @@ G_BEGIN_DECLS 191*4882a593Smuzhiyun typedef struct _GstWlWindow GstWlWindow; 192*4882a593Smuzhiyun typedef struct _GstWlWindowClass GstWlWindowClass; 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun+typedef enum 195*4882a593Smuzhiyun+{ 196*4882a593Smuzhiyun+ GST_WL_WINDOW_STRETCH = 0, 197*4882a593Smuzhiyun+ GST_WL_WINDOW_FIT = 1, 198*4882a593Smuzhiyun+ GST_WL_WINDOW_CROP = 2, 199*4882a593Smuzhiyun+} GstWlWindowFillMode; 200*4882a593Smuzhiyun+ 201*4882a593Smuzhiyun struct _GstWlWindow 202*4882a593Smuzhiyun { 203*4882a593Smuzhiyun GObject parent_instance; 204*4882a593Smuzhiyun@@ -71,6 +78,8 @@ struct _GstWlWindow 205*4882a593Smuzhiyun /* when this is not set both the area_surface and the video_surface are not 206*4882a593Smuzhiyun * visible and certain steps should be skipped */ 207*4882a593Smuzhiyun gboolean is_area_surface_mapped; 208*4882a593Smuzhiyun+ 209*4882a593Smuzhiyun+ GstWlWindowFillMode fill_mode; 210*4882a593Smuzhiyun }; 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun struct _GstWlWindowClass 213*4882a593Smuzhiyun-- 214*4882a593Smuzhiyun2.20.1 215*4882a593Smuzhiyun 216