1From 11b559342c5bed99b46652b68e35bfea171d1a86 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Fri, 12 Nov 2021 11:14:37 +0800 4Subject: [PATCH 26/41] waylandsink: Support NV12_10LE40 and 5 NV12|NV12_10LE40|NV16 (AFBC) 6 7Tested on RK356x with: 8export GST_MPP_VIDEODEC_DEFAULT_ARM_AFBC=1 9gst-play-1.0 video.mp4 --videosink=waylandsink 10 11Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 12--- 13 ext/wayland/gstwaylandsink.c | 86 ++++++++++++++++++++++++- 14 gst-libs/gst/wayland/gstwldisplay.c | 37 ++++++++++- 15 gst-libs/gst/wayland/gstwldisplay.h | 6 ++ 16 gst-libs/gst/wayland/gstwllinuxdmabuf.c | 26 +++++++- 17 gst-libs/gst/wayland/gstwlvideoformat.c | 1 + 18 gst-libs/gst/wayland/gstwlvideoformat.h | 44 +++++++++++++ 19 gst-libs/gst/wayland/gstwlwindow.c | 50 +++++++++++--- 20 gst-libs/gst/wayland/gstwlwindow.h | 4 ++ 21 8 files changed, 243 insertions(+), 11 deletions(-) 22 23diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c 24index 5e142e9..b26b7ee 100644 25--- a/ext/wayland/gstwaylandsink.c 26+++ b/ext/wayland/gstwaylandsink.c 27@@ -74,7 +74,7 @@ GST_DEBUG_CATEGORY (gstwayland_debug); 28 29 #define WL_VIDEO_FORMATS \ 30 "{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, " \ 31- "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, NV61, " \ 32+ "RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, NV61, NV12_10LE40, " \ 33 "YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }" 34 35 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", 36@@ -647,6 +647,53 @@ gst_wayland_sink_event (GstBaseSink * bsink, GstEvent * event) 37 return ret; 38 } 39 40+static GstCaps * 41+gst_wayland_sink_fixup_caps (GstWaylandSink * self, GstCaps * caps) 42+{ 43+ GstCaps *tmp_caps = NULL; 44+ 45+ /* HACK: Allow nv12-10le40 and arm-afbc in main caps */ 46+ 47+ if (gst_wl_display_support_nv12_10le40 (self->display)) { 48+ tmp_caps = gst_caps_from_string ( 49+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, 50+ "NV12_10LE40")); 51+ 52+ /* NV15(AFBC) */ 53+ if (gst_wl_display_support_afbc (self->display)) { 54+ gst_caps_ref (tmp_caps); 55+ gst_caps_append (caps, tmp_caps); 56+ 57+ gst_caps_set_simple (tmp_caps, "arm-afbc", G_TYPE_INT, 1, NULL); 58+ } 59+ 60+ gst_caps_append (caps, tmp_caps); 61+ } 62+ 63+ /* NV12|NV16 (AFBC) */ 64+ if (gst_wl_display_support_afbc (self->display)) { 65+ if (gst_wl_display_check_format_for_dmabuf (self->display, 66+ GST_VIDEO_FORMAT_NV12)) { 67+ tmp_caps = gst_caps_from_string ( 68+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, 69+ "NV12")); 70+ gst_caps_set_simple (tmp_caps, "arm-afbc", G_TYPE_INT, 1, NULL); 71+ gst_caps_append (caps, tmp_caps); 72+ } 73+ 74+ if (gst_wl_display_check_format_for_dmabuf (self->display, 75+ GST_VIDEO_FORMAT_NV16)) { 76+ tmp_caps = gst_caps_from_string ( 77+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, 78+ "NV16")); 79+ gst_caps_set_simple (tmp_caps, "arm-afbc", G_TYPE_INT, 1, NULL); 80+ gst_caps_append (caps, tmp_caps); 81+ } 82+ } 83+ 84+ return caps; 85+} 86+ 87 static GstCaps * 88 gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) 89 { 90@@ -699,6 +746,8 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) 91 gst_structure_take_value (gst_caps_get_structure (caps, 1), "format", 92 &dmabuf_list); 93 94+ caps = gst_wayland_sink_fixup_caps (self, caps); 95+ 96 GST_DEBUG_OBJECT (self, "display caps: %" GST_PTR_FORMAT, caps); 97 } 98 99@@ -746,6 +795,8 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) 100 GstWaylandSink *self = GST_WAYLAND_SINK (bsink);; 101 gboolean use_dmabuf; 102 GstVideoFormat format; 103+ GstStructure *s; 104+ gint value; 105 106 GST_DEBUG_OBJECT (self, "set caps %" GST_PTR_FORMAT, caps); 107 108@@ -753,6 +804,15 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) 109 if (!gst_video_info_from_caps (&self->video_info, caps)) 110 goto invalid_format; 111 112+ /* parse AFBC from caps */ 113+ s = gst_caps_get_structure (caps, 0); 114+ if (gst_structure_get_int (s, "arm-afbc", &value)) { 115+ if (value) 116+ GST_VIDEO_INFO_SET_AFBC (&self->video_info); 117+ else 118+ GST_VIDEO_INFO_UNSET_AFBC (&self->video_info); 119+ } 120+ 121 format = GST_VIDEO_INFO_FORMAT (&self->video_info); 122 self->video_info_changed = TRUE; 123 124@@ -798,9 +858,17 @@ gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) 125 GstBufferPool *pool = NULL; 126 gboolean need_pool; 127 GstAllocator *alloc; 128+ GstStructure *s; 129+ gint value; 130 131 gst_query_parse_allocation (query, &caps, &need_pool); 132 133+ s = gst_caps_get_structure (caps, 0); 134+ if (gst_structure_get_int (s, "arm-afbc", &value) && value) { 135+ GST_DEBUG_OBJECT (self, "no allocation for AFBC"); 136+ return FALSE; 137+ } 138+ 139 if (need_pool) 140 pool = gst_wayland_create_pool (self, caps); 141 142@@ -811,6 +879,7 @@ gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) 143 alloc = gst_wl_shm_allocator_get (); 144 gst_query_add_allocation_param (query, alloc, NULL); 145 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); 146+ gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); 147 g_object_unref (alloc); 148 149 return TRUE; 150@@ -884,6 +953,7 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) 151 GstWaylandSink *self = GST_WAYLAND_SINK (vsink); 152 GstBuffer *to_render; 153 GstWlBuffer *wlbuffer; 154+ GstVideoCropMeta *crop; 155 GstVideoMeta *vmeta; 156 GstVideoFormat format; 157 GstVideoInfo old_vinfo; 158@@ -923,6 +993,11 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) 159 } 160 } 161 162+ crop = gst_buffer_get_video_crop_meta (buffer); 163+ if (crop) 164+ gst_wl_window_ensure_crop (self->window, crop->x, crop->y, 165+ crop->width, crop->height); 166+ 167 /* drop buffers until we get a frame callback */ 168 if (self->redraw_pending) { 169 GST_LOG_OBJECT (self, "buffer %" GST_PTR_FORMAT " dropped (redraw pending)", 170@@ -977,6 +1052,9 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) 171 &self->video_info); 172 } 173 174+ if (!wbuf && GST_VIDEO_INFO_IS_AFBC (&self->video_info)) 175+ goto no_afbc; 176+ 177 if (!wbuf && gst_wl_display_check_format_for_shm (self->display, format)) { 178 if (gst_buffer_n_memory (buffer) == 1 && gst_is_fd_memory (mem)) 179 wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, self->display, 180@@ -1107,6 +1185,12 @@ no_wl_buffer: 181 ret = GST_FLOW_ERROR; 182 goto done; 183 } 184+no_afbc: 185+ { 186+ GST_ERROR_OBJECT (self, "could not import AFBC"); 187+ ret = GST_FLOW_ERROR; 188+ goto done; 189+ } 190 activate_failed: 191 { 192 GST_ERROR_OBJECT (self, "failed to activate bufferpool."); 193diff --git a/gst-libs/gst/wayland/gstwldisplay.c b/gst-libs/gst/wayland/gstwldisplay.c 194index 71a5dde..3e11211 100644 195--- a/gst-libs/gst/wayland/gstwldisplay.c 196+++ b/gst-libs/gst/wayland/gstwldisplay.c 197@@ -61,6 +61,9 @@ typedef struct _GstWlDisplayPrivate 198 GMutex buffers_mutex; 199 GHashTable *buffers; 200 gboolean shutting_down; 201+ 202+ gboolean support_afbc; 203+ gboolean support_nv12_10le40; 204 } GstWlDisplayPrivate; 205 206 G_DEFINE_TYPE_WITH_CODE (GstWlDisplay, gst_wl_display, G_TYPE_OBJECT, 207@@ -69,6 +72,20 @@ G_DEFINE_TYPE_WITH_CODE (GstWlDisplay, gst_wl_display, G_TYPE_OBJECT, 208 "wldisplay", 0, "wldisplay library"); 209 ); 210 211+gboolean 212+gst_wl_display_support_afbc (GstWlDisplay * self) 213+{ 214+ GstWlDisplayPrivate *priv = gst_wl_display_get_instance_private (self); 215+ return priv->support_afbc; 216+} 217+ 218+gboolean 219+gst_wl_display_support_nv12_10le40 (GstWlDisplay * self) 220+{ 221+ GstWlDisplayPrivate *priv = gst_wl_display_get_instance_private (self); 222+ return priv->support_nv12_10le40; 223+} 224+ 225 static void gst_wl_display_finalize (GObject * gobject); 226 227 static void 228@@ -187,10 +204,28 @@ dmabuf_format (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, 229 230 if (gst_wl_dmabuf_format_to_video_format (format) != GST_VIDEO_FORMAT_UNKNOWN) 231 g_array_append_val (priv->dmabuf_formats, format); 232+ 233+ if (format == DRM_FORMAT_NV15) 234+ priv->support_nv12_10le40 = TRUE; 235+} 236+ 237+static void 238+dmabuf_modifier (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, 239+ uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) 240+{ 241+ GstWlDisplay *self = data; 242+ GstWlDisplayPrivate *priv = gst_wl_display_get_instance_private (self); 243+ uint64_t modifier = ((uint64_t) modifier_hi << 32) | modifier_lo; 244+ 245+ if (modifier == DRM_AFBC_MODIFIER) 246+ priv->support_afbc = TRUE; 247+ 248+ dmabuf_format (data, zwp_linux_dmabuf, format); 249 } 250 251 static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { 252 dmabuf_format, 253+ dmabuf_modifier, 254 }; 255 256 gboolean 257@@ -277,7 +312,7 @@ registry_handle_global (void *data, struct wl_registry *registry, 258 wl_registry_bind (registry, id, &wp_viewporter_interface, 1); 259 } else if (g_strcmp0 (interface, "zwp_linux_dmabuf_v1") == 0) { 260 priv->dmabuf = 261- wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 2); 262+ wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 3); 263 zwp_linux_dmabuf_v1_add_listener (priv->dmabuf, &dmabuf_listener, self); 264 } 265 } 266diff --git a/gst-libs/gst/wayland/gstwldisplay.h b/gst-libs/gst/wayland/gstwldisplay.h 267index eb07e4f..c130b79 100644 268--- a/gst-libs/gst/wayland/gstwldisplay.h 269+++ b/gst-libs/gst/wayland/gstwldisplay.h 270@@ -35,6 +35,12 @@ struct _GstWlDisplay 271 GObject parent_instance; 272 }; 273 274+GST_WL_API 275+gboolean gst_wl_display_support_afbc (GstWlDisplay * self); 276+ 277+GST_WL_API 278+gboolean gst_wl_display_support_nv12_10le40 (GstWlDisplay * self); 279+ 280 GST_WL_API 281 GstWlDisplay *gst_wl_display_new (const gchar * name, GError ** error); 282 283diff --git a/gst-libs/gst/wayland/gstwllinuxdmabuf.c b/gst-libs/gst/wayland/gstwllinuxdmabuf.c 284index 2d5bb6b..65b6d8f 100644 285--- a/gst-libs/gst/wayland/gstwllinuxdmabuf.c 286+++ b/gst-libs/gst/wayland/gstwllinuxdmabuf.c 287@@ -57,8 +57,10 @@ gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf, 288 int format; 289 guint i, width, height; 290 guint nplanes, flags = 0; 291+ gfloat stride_scale = 1.0f; 292 struct zwp_linux_buffer_params_v1 *params; 293 ConstructBufferData data; 294+ guint64 modifier = GST_VIDEO_INFO_IS_AFBC (info) ? DRM_AFBC_MODIFIER : 0; 295 296 g_return_val_if_fail (gst_wl_display_check_format_for_dmabuf (display, 297 GST_VIDEO_INFO_FORMAT (info)), NULL); 298@@ -74,6 +76,27 @@ gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf, 299 G_GSSIZE_FORMAT " (%d x %d), format %s", info->size, width, height, 300 gst_wl_dmabuf_format_to_string (format)); 301 302+ if (GST_VIDEO_INFO_IS_AFBC (info)) { 303+ /* Mali uses these formats instead */ 304+ if (format == DRM_FORMAT_NV12) { 305+ format = DRM_FORMAT_YUV420_8BIT; 306+ nplanes = 1; 307+ stride_scale = 1.5; 308+ } else if (format == DRM_FORMAT_NV15) { 309+ format = DRM_FORMAT_YUV420_10BIT; 310+ nplanes = 1; 311+ stride_scale = 1.5; 312+ } else if (format == DRM_FORMAT_NV16) { 313+ format = DRM_FORMAT_YUYV; 314+ nplanes = 1; 315+ stride_scale = 2; 316+ } else { 317+ GST_ERROR_OBJECT (mem->allocator, "unsupported format for AFBC"); 318+ data.wbuf = NULL; 319+ goto out; 320+ } 321+ } 322+ 323 /* Creation and configuration of planes */ 324 params = zwp_linux_dmabuf_v1_create_params (gst_wl_display_get_dmabuf_v1 325 (display)); 326@@ -84,11 +107,12 @@ gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf, 327 328 offset = GST_VIDEO_INFO_PLANE_OFFSET (info, i); 329 stride = GST_VIDEO_INFO_PLANE_STRIDE (info, i); 330+ stride *= stride_scale; 331 if (gst_buffer_find_memory (buf, offset, 1, &mem_idx, &length, &skip)) { 332 GstMemory *m = gst_buffer_peek_memory (buf, mem_idx); 333 gint fd = gst_dmabuf_memory_get_fd (m); 334 zwp_linux_buffer_params_v1_add (params, fd, i, m->offset + skip, 335- stride, 0, 0); 336+ stride, modifier >> 32, modifier & 0xFFFFFFFF); 337 } else { 338 GST_ERROR_OBJECT (mem->allocator, "memory does not seem to contain " 339 "enough data for the specified format"); 340diff --git a/gst-libs/gst/wayland/gstwlvideoformat.c b/gst-libs/gst/wayland/gstwlvideoformat.c 341index 44a9536..003daa6 100644 342--- a/gst-libs/gst/wayland/gstwlvideoformat.c 343+++ b/gst-libs/gst/wayland/gstwlvideoformat.c 344@@ -71,6 +71,7 @@ static const wl_VideoFormat wl_formats[] = { 345 {WL_SHM_FORMAT_UYVY, DRM_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY}, 346 {WL_SHM_FORMAT_AYUV, DRM_FORMAT_AYUV, GST_VIDEO_FORMAT_AYUV}, 347 {WL_SHM_FORMAT_NV12, DRM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12}, 348+ {-1, DRM_FORMAT_NV15, GST_VIDEO_FORMAT_NV12_10LE40}, 349 {WL_SHM_FORMAT_NV21, DRM_FORMAT_NV21, GST_VIDEO_FORMAT_NV21}, 350 {WL_SHM_FORMAT_NV16, DRM_FORMAT_NV16, GST_VIDEO_FORMAT_NV16}, 351 {WL_SHM_FORMAT_NV61, DRM_FORMAT_NV61, GST_VIDEO_FORMAT_NV61}, 352diff --git a/gst-libs/gst/wayland/gstwlvideoformat.h b/gst-libs/gst/wayland/gstwlvideoformat.h 353index bc36a08..abf579c 100644 354--- a/gst-libs/gst/wayland/gstwlvideoformat.h 355+++ b/gst-libs/gst/wayland/gstwlvideoformat.h 356@@ -27,8 +27,52 @@ 357 358 #include <gst/video/video.h> 359 360+#include <drm_fourcc.h> 361+ 362 G_BEGIN_DECLS 363 364+#ifndef DRM_FORMAT_NV15 365+#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') 366+#endif 367+ 368+#ifndef DRM_FORMAT_YUV420_8BIT 369+#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') 370+#endif 371+ 372+#ifndef DRM_FORMAT_YUV420_10BIT 373+#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') 374+#endif 375+ 376+#ifndef DRM_FORMAT_MOD_VENDOR_ARM 377+#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 378+#endif 379+ 380+#ifndef DRM_FORMAT_MOD_ARM_AFBC 381+#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) 382+#endif 383+ 384+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 385+#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) 386+#endif 387+ 388+#ifndef AFBC_FORMAT_MOD_SPARSE 389+#define AFBC_FORMAT_MOD_SPARSE (((__u64)1) << 6) 390+#endif 391+ 392+#define DRM_AFBC_MODIFIER \ 393+ (DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_SPARSE) | \ 394+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)) 395+ 396+#ifndef GST_VIDEO_FLAG_ARM_AFBC 397+#define GST_VIDEO_FLAG_ARM_AFBC (1UL << 31) 398+#define GST_VIDEO_INFO_SET_AFBC(i) \ 399+ GST_VIDEO_INFO_FLAG_SET (i, GST_VIDEO_FLAG_ARM_AFBC) 400+#define GST_VIDEO_INFO_UNSET_AFBC(i) \ 401+ GST_VIDEO_INFO_FLAG_UNSET (i, GST_VIDEO_FLAG_ARM_AFBC) 402+#define GST_VIDEO_INFO_IS_AFBC(i) \ 403+ GST_VIDEO_INFO_FLAG_IS_SET (i, GST_VIDEO_FLAG_ARM_AFBC) 404+#endif 405+ 406 GST_WL_API 407 void gst_wl_videoformat_init_once (void); 408 409diff --git a/gst-libs/gst/wayland/gstwlwindow.c b/gst-libs/gst/wayland/gstwlwindow.c 410index 7dc0da5..df60a67 100644 411--- a/gst-libs/gst/wayland/gstwlwindow.c 412+++ b/gst-libs/gst/wayland/gstwlwindow.c 413@@ -66,6 +66,9 @@ typedef struct _GstWlWindowPrivate 414 /* the size of the video in the buffers */ 415 gint video_width, video_height; 416 417+ gint crop_x, crop_y, crop_w, crop_h; 418+ gboolean crop_dirty; 419+ 420 enum wl_output_transform buffer_transform; 421 422 /* when this is not set both the area_surface and the video_surface are not 423@@ -255,6 +258,29 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock) 424 return self; 425 } 426 427+void 428+gst_wl_window_ensure_crop (GstWlWindow * self, gint x, gint y, gint w, gint h) 429+{ 430+ GstWlWindowPrivate *priv; 431+ 432+ if (!self) 433+ return; 434+ 435+ priv = gst_wl_window_get_instance_private (self); 436+ 437+ if (priv->crop_x == x && priv->crop_y == y && 438+ priv->crop_w == w && priv->crop_h == h) 439+ return; 440+ 441+ priv->crop_x = x; 442+ priv->crop_y = y; 443+ priv->crop_w = w; 444+ priv->crop_h = h; 445+ priv->crop_dirty = TRUE; 446+ 447+ GST_LOG_OBJECT (self, "crop %dx%d-%dx%d", x, y, w, h); 448+} 449+ 450 void 451 gst_wl_window_ensure_fill_mode (GstWlWindow * self, 452 GstWlWindowFillMode fill_mode) 453@@ -523,6 +549,14 @@ gst_wl_window_resize_video_surface (GstWlWindow * self, gboolean commit) 454 dst.w = priv->render_rectangle.w; 455 dst.h = priv->render_rectangle.h; 456 457+ if (priv->crop_w && priv->crop_h) { 458+ src.x = priv->crop_x; 459+ src.y = priv->crop_y; 460+ src.w = priv->crop_w; 461+ src.h = priv->crop_h; 462+ } 463+ priv->crop_dirty = FALSE; 464+ 465 /* center the video_subsurface inside area_subsurface */ 466 if (priv->video_viewport) { 467 if (priv->fill_mode == GST_WL_WINDOW_STRETCH) { 468@@ -537,22 +571,21 @@ gst_wl_window_resize_video_surface (GstWlWindow * self, gboolean commit) 469 470 if (src_ratio < dst_ratio) { 471 int h = src.w / dst_ratio; 472- src.y = (src.h - h) / 2; 473+ src.y += (src.h - h) / 2; 474 src.h = h; 475 } else if (src_ratio > dst_ratio) { 476 int w = src.h * dst_ratio; 477- src.x = (src.w - w) / 2; 478+ src.x += (src.w - w) / 2; 479 src.w = w; 480 } 481 482- wp_viewport_set_source (priv->video_viewport, 483- wl_fixed_from_int (src.x), wl_fixed_from_int (src.y), 484- wl_fixed_from_int (src.w), wl_fixed_from_int (src.h)); 485- 486 res = dst; 487 } 488 489 wp_viewport_set_destination (priv->video_viewport, res.w, res.h); 490+ wp_viewport_set_source (priv->video_viewport, 491+ wl_fixed_from_int (src.x), wl_fixed_from_int (src.y), 492+ wl_fixed_from_int (src.w), wl_fixed_from_int (src.h)); 493 } else { 494 gst_video_center_rect (&src, &dst, &res, FALSE); 495 } 496@@ -597,13 +630,14 @@ gst_wl_window_render (GstWlWindow * self, GstWlBuffer * buffer, 497 GstWlWindowPrivate *priv = gst_wl_window_get_instance_private (self); 498 499 if (G_UNLIKELY (info)) { 500- priv->video_width = 501- gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d); 502+ priv->video_width = info->width; 503 priv->video_height = info->height; 504 505 wl_subsurface_set_sync (priv->video_subsurface); 506 gst_wl_window_resize_video_surface (self, FALSE); 507 gst_wl_window_set_opaque (self, info); 508+ } else if (priv->crop_dirty) { 509+ gst_wl_window_resize_video_surface (self, FALSE); 510 } 511 512 if (G_LIKELY (buffer)) { 513diff --git a/gst-libs/gst/wayland/gstwlwindow.h b/gst-libs/gst/wayland/gstwlwindow.h 514index 1571ece..8f02f00 100644 515--- a/gst-libs/gst/wayland/gstwlwindow.h 516+++ b/gst-libs/gst/wayland/gstwlwindow.h 517@@ -47,6 +47,10 @@ struct _GstWlWindow 518 GObject parent_instance; 519 }; 520 521+GST_WL_API 522+void gst_wl_window_ensure_crop (GstWlWindow * self, 523+ gint x, gint y, gint w, gint h); 524+ 525 GST_WL_API 526 void gst_wl_window_ensure_fill_mode (GstWlWindow * self, 527 GstWlWindowFillMode fill_mode); 528-- 5292.20.1 530 531