1 /* GStreamer Wayland video sink
3 * Copyright (C) 2014 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
21 /* GstWlBuffer wraps wl_buffer and provides a mechanism for preventing
22 * buffers from being re-used while the compositor is using them. This
23 * is achieved by adding a reference to the GstBuffer as soon as its
24 * associated wl_buffer is sent to the compositor and by removing this
25 * reference as soon as the compositor sends a wl_buffer::release message.
27 * This mechanism is a bit complicated, though, because it adds cyclic
28 * references that can be dangerous. The reference cycles looks like:
31 * | GstWlDisplay | ---------------------------->
35 * ----------------- ------------- ---------------
36 * | GstBufferPool | --> | GstBuffer | ==> | GstWlBuffer |
38 * ----------------- ------------- ---------------
40 * A GstBufferPool normally holds references to its GstBuffers and each buffer
41 * holds a reference to a GstWlBuffer (saved in the GstMiniObject weak ref data).
42 * When a GstBuffer is in use, it holds a reference back to the pool and the
43 * pool doesn't hold a reference to the GstBuffer. When the GstBuffer is unrefed
44 * externally, it returns back to the pool and the pool holds again a reference
47 * Now when the compositor is using a buffer, the GstWlBuffer also holds a ref
48 * to the GstBuffer, which prevents it from returning to the pool. When the
49 * last GstWlBuffer receives a release event and unrefs the last GstBuffer,
50 * the GstBufferPool will be able to stop and if no-one is holding a strong
51 * ref to it, it will be destroyed. This will destroy the pool's GstBuffers and
52 * also the GstWlBuffers. This will all happen in the same context of the last
53 * gst_buffer_unref, which will be called from the buffer_release() callback.
55 * The problem here lies in the fact that buffer_release() will be called
56 * from the event loop thread of GstWlDisplay, so it's as if the display
57 * holds a reference to the GstWlBuffer, but without having an actual reference.
58 * When we kill the display, there is no way for the GstWlBuffer, the associated
59 * GstBuffer and the GstBufferPool to get destroyed, so we are going to leak a
60 * fair amount of memory.
62 * Normally, this rarely happens, because the compositor releases buffers
63 * almost immediately and when waylandsink stops, they are already released.
65 * However, we want to be absolutely certain, so a solution is introduced
66 * by registering all the GstWlBuffers with the display and explicitly
67 * releasing all the buffer references as soon as the display is destroyed.
69 * When the GstWlDisplay is finalized, it takes a reference to all the
70 * registered GstWlBuffers and then calls gst_wl_buffer_force_release_and_unref,
71 * which releases the potential reference to the GstBuffer, destroys the
72 * underlying wl_buffer and removes the reference that GstWlDisplay is holding.
73 * At that point, either the GstBuffer is alive somewhere and still holds a ref
74 * to the GstWlBuffer, which it will release when it gets destroyed, or the
75 * GstBuffer was destroyed in the meantime and the GstWlBuffer gets destroyed
76 * as soon as we remove the reference that GstWlDisplay holds.
81 GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
82 #define GST_CAT_DEFAULT gstwayland_debug
84 G_DEFINE_TYPE (GstWlBuffer, gst_wl_buffer, G_TYPE_OBJECT);
87 gst_wl_buffer_dispose (GObject * gobject)
89 GstWlBuffer *self = GST_WL_BUFFER (gobject);
91 GST_TRACE_OBJECT (self, "dispose");
93 /* if the display is shutting down and we are trying to dipose
94 * the GstWlBuffer from another thread, unregister_buffer() will
95 * block and in the end the display will increase the refcount
96 * of this GstWlBuffer, so it will not be finalized */
98 gst_wl_display_unregister_buffer (self->display, self->gstmem);
101 G_OBJECT_CLASS (gst_wl_buffer_parent_class)->dispose (gobject);
105 gst_wl_buffer_finalize (GObject * gobject)
107 GstWlBuffer *self = GST_WL_BUFFER (gobject);
109 GST_TRACE_OBJECT (self, "finalize");
112 wl_buffer_destroy (self->wlbuffer);
114 G_OBJECT_CLASS (gst_wl_buffer_parent_class)->finalize (gobject);
118 gst_wl_buffer_class_init (GstWlBufferClass * klass)
120 GObjectClass *object_class = (GObjectClass *) klass;
122 object_class->dispose = gst_wl_buffer_dispose;
123 object_class->finalize = gst_wl_buffer_finalize;
127 gst_wl_buffer_init (GstWlBuffer * self)
132 buffer_release (void *data, struct wl_buffer *wl_buffer)
134 GstWlBuffer *self = data;
135 GstBuffer *buf = self->current_gstbuffer;
137 GST_LOG_OBJECT (self, "wl_buffer::release (GstBuffer: %p)", buf);
139 self->used_by_compositor = FALSE;
140 self->current_gstbuffer = NULL;
142 /* unref should be last, because it may end up destroying the GstWlBuffer */
143 gst_buffer_unref (buf);
146 static const struct wl_buffer_listener buffer_listener = {
151 gstmemory_disposed (GstWlBuffer * self)
153 g_assert (!self->used_by_compositor);
155 GST_TRACE_OBJECT (self, "owning GstMemory was finalized");
157 /* this will normally destroy the GstWlBuffer, unless the display is
158 * finalizing and it has taken an additional reference to it */
159 g_object_unref (self);
163 gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, struct wl_buffer *wlbuffer,
164 GstWlDisplay * display)
168 self = g_object_new (GST_TYPE_WL_BUFFER, NULL);
169 self->current_gstbuffer = gstbuffer;
170 self->wlbuffer = wlbuffer;
171 self->display = display;
172 self->gstmem = gst_buffer_peek_memory (gstbuffer, 0);
174 gst_wl_display_register_buffer (self->display, self->gstmem, self);
176 wl_buffer_add_listener (self->wlbuffer, &buffer_listener, self);
178 gst_mini_object_weak_ref (GST_MINI_OBJECT (self->gstmem),
179 (GstMiniObjectNotify) gstmemory_disposed, self);
186 gst_buffer_get_wl_buffer (GstWlDisplay * display, GstBuffer * gstbuffer)
194 mem0 = gst_buffer_peek_memory (gstbuffer, 0);
196 wlbuf = gst_wl_display_lookup_buffer (display, mem0);
198 wlbuf->current_gstbuffer = gstbuffer;
204 gst_wl_buffer_force_release_and_unref (GstBuffer * buf, GstWlBuffer * self)
206 /* Force a buffer release.
207 * At this point, the GstWlDisplay has killed its event loop,
208 * so we don't need to worry about buffer_release() being called
209 * at the same time from the event loop thread */
210 if (self->used_by_compositor) {
211 GST_DEBUG_OBJECT (self, "forcing wl_buffer::release (GstBuffer: %p)",
212 self->current_gstbuffer);
213 self->used_by_compositor = FALSE;
214 gst_buffer_unref (self->current_gstbuffer);
217 /* Finalize this GstWlBuffer early.
218 * This method has been called as a result of the display shutting down,
219 * so we need to stop using any wayland resources and disconnect from
220 * the display. The GstWlBuffer stays alive, though, to avoid race
221 * conditions with the GstBuffer being destroyed from another thread.
222 * The last reference is either owned by the GstBuffer or by us and
223 * it will be released at the end of this function. */
224 GST_TRACE_OBJECT (self, "finalizing early");
225 wl_buffer_destroy (self->wlbuffer);
226 self->wlbuffer = NULL;
227 self->display = NULL;
228 self->current_gstbuffer = NULL;
230 /* remove the reference that the caller (GstWlDisplay) owns */
231 g_object_unref (self);
235 gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface)
237 if (self->used_by_compositor) {
238 GST_DEBUG_OBJECT (self, "buffer used by compositor %p",
239 self->current_gstbuffer);
243 wl_surface_attach (surface, self->wlbuffer, 0, 0);
245 /* Add a reference to the buffer. This represents the fact that
246 * the compositor is using the buffer and it should not return
247 * back to the pool and be re-used until the compositor releases it. */
248 gst_buffer_ref (self->current_gstbuffer);
249 self->used_by_compositor = TRUE;