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