if (sink->last_buffer)
gst_buffer_unref (sink->last_buffer);
- if (sink->display) {
- /* the display must be stopped before droping our reference to it
- * - see the comment on wlbuffer.c for details */
- gst_wl_display_stop (sink->display);
+ if (sink->display)
g_object_unref (sink->display);
- }
if (sink->window)
g_object_unref (sink->window);
if (sink->pool)
* restarted (GstVideoOverlay behaves like that in other sinks)
*/
if (sink->display && !sink->window) { /* -> the window was toplevel */
- /* the display must be stopped before droping our reference to it
- * - see the comment on wlbuffer.c for details */
- gst_wl_display_stop (sink->display);
g_clear_object (&sink->display);
}
g_mutex_unlock (&sink->display_lock);
* references that can be dangerous. The reference cycles looks like:
*
* ----------------
- * | GstWlDisplay | ---------------------------------->
- * ---------------- |
- * ^ |
- * | V
- * ------------------------ ------------- ---------------
- * | GstWaylandBufferPool | --> | GstBuffer | ==> | GstWlBuffer |
- * | | <-- | | <-- | |
- * ------------------------ ------------- ---------------
+ * | GstWlDisplay | ---------------------------->
+ * ---------------- |
+ * |
+ * V
+ * ----------------- ------------- ---------------
+ * | GstBufferPool | --> | GstBuffer | ==> | GstWlBuffer |
+ * | | <-- | | <-- | |
+ * ----------------- ------------- ---------------
*
* A GstBufferPool normally holds references to its GstBuffers and each buffer
* holds a reference to a GstWlBuffer (saved in the GstMiniObject qdata).
* to the GstBuffer, which prevents it from returning to the pool. When the
* last GstWlBuffer receives a release event and unrefs the last GstBuffer,
* the GstBufferPool will be able to stop and if no-one is holding a strong
- * ref to it, it will be destroyed. This will destroy that last GstBuffer and
- * also the GstWlBuffer. This will all happen in the same context of the
+ * ref to it, it will be destroyed. This will destroy the pool's GstBuffers and
+ * also the GstWlBuffers. This will all happen in the same context of the last
* gst_buffer_unref, which will be called from the buffer_release() callback.
*
- * The big problem here lies in the fact that buffer_release() will be called
- * from the event loop thread of GstWlDisplay and the second big problem is
- * that the GstWaylandBufferPool holds a strong ref to the GstWlDisplay.
- * Therefore, if the buffer_release() causes the pool to be destroyed, it may
- * also cause the GstWlDisplay to be destroyed and that will happen in the
- * context of the event loop thread that GstWlDisplay runs. Destroying the
- * GstWlDisplay will need to join the thread (from inside the thread!) and boom.
+ * The problem here lies in the fact that buffer_release() will be called
+ * from the event loop thread of GstWlDisplay, so it's as if the display
+ * holds a reference to the GstWlBuffer, but without having an actual reference.
+ * When we kill the display, there is no way for the GstWlBuffer, the associated
+ * GstBuffer and the GstBufferPool to get destroyed, so we are going to leak a
+ * fair ammount of memory.
*
* Normally, this will never happen, even if we don't take special care for it,
* because the compositor releases buffers almost immediately and when
* waylandsink stops, they are already released.
*
* However, we want to be absolutely certain, so a solution is introduced
- * by explicitly releasing all the buffer references and destroying the
- * GstWlBuffers as soon as we know that we are not going to use them again.
- * All the GstWlBuffers are registered in a hash set inside GstWlDisplay
- * and there is gst_wl_display_stop(), which stops the event loop thread
- * and releases all the buffers explicitly. This gets called from GstWaylandSink
- * right before dropping its own reference to the GstWlDisplay, leaving
- * a possible last (but safe now!) reference to the pool, which may be
- * referenced by an upstream element.
+ * by registering all the GstWlBuffers with the display and explicitly
+ * releasing all the buffer references and destroying the GstWlBuffers as soon
+ * as the display is destroyed.
*/
#include "wlbuffer.h"
{
GstWlDisplay *self = GST_WL_DISPLAY (gobject);
+ gst_poll_set_flushing (self->wl_fd_poll, TRUE);
+ g_thread_join (self->thread);
+
+ g_hash_table_foreach (self->buffers,
+ (GHFunc) gst_wl_buffer_force_release_and_unref, NULL);
+ g_hash_table_remove_all (self->buffers);
+
g_array_unref (self->formats);
gst_poll_free (self->wl_fd_poll);
g_hash_table_unref (self->buffers);
}
void
-gst_wl_display_stop (GstWlDisplay * self)
-{
- gst_poll_set_flushing (self->wl_fd_poll, TRUE);
- g_thread_join (self->thread);
-
- g_hash_table_foreach (self->buffers,
- (GHFunc) gst_wl_buffer_force_release_and_unref, NULL);
- g_hash_table_remove_all (self->buffers);
-}
-
-void
gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf)
{
g_hash_table_add (self->buffers, buf);