diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index 4957d1d8f5..8c6fdd0e71 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -655,7 +655,7 @@ render_last_buffer (GstWaylandSink * sink, gboolean redraw) struct wl_surface *surface; struct wl_callback *callback; - wlbuffer = gst_buffer_get_wl_buffer (sink->last_buffer); + wlbuffer = gst_buffer_get_wl_buffer (sink->display, sink->last_buffer); surface = gst_wl_window_get_wl_surface (sink->window); sink->redraw_pending = TRUE; @@ -723,7 +723,7 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) if (G_UNLIKELY (sink->window->render_rectangle.w == 0)) goto no_window_size; - wlbuffer = gst_buffer_get_wl_buffer (buffer); + wlbuffer = gst_buffer_get_wl_buffer (sink->display, buffer); if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) { GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, " @@ -807,7 +807,7 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) if (ret != GST_FLOW_OK) goto no_buffer; - wlbuffer = gst_buffer_get_wl_buffer (to_render); + wlbuffer = gst_buffer_get_wl_buffer (sink->display, to_render); /* attach a wl_buffer if there isn't one yet */ if (G_UNLIKELY (!wlbuffer)) { diff --git a/ext/wayland/wlbuffer.c b/ext/wayland/wlbuffer.c index 74d62162f5..50d3e6af70 100644 --- a/ext/wayland/wlbuffer.c +++ b/ext/wayland/wlbuffer.c @@ -38,7 +38,7 @@ * ----------------- ------------- --------------- * * A GstBufferPool normally holds references to its GstBuffers and each buffer - * holds a reference to a GstWlBuffer (saved in the GstMiniObject qdata). + * holds a reference to a GstWlBuffer (saved in the GstMiniObject weak ref data). * When a GstBuffer is in use, it holds a reference back to the pool and the * pool doesn't hold a reference to the GstBuffer. When the GstBuffer is unrefed * externally, it returns back to the pool and the pool holds again a reference @@ -83,8 +83,6 @@ GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug); G_DEFINE_TYPE (GstWlBuffer, gst_wl_buffer, G_TYPE_OBJECT); -static G_DEFINE_QUARK (GstWlBufferQDataQuark, gst_wl_buffer_qdata); - static void gst_wl_buffer_dispose (GObject * gobject) { @@ -97,7 +95,7 @@ gst_wl_buffer_dispose (GObject * gobject) * block and in the end the display will increase the refcount * of this GstWlBuffer, so it will not be finalized */ if (self->display) - gst_wl_display_unregister_buffer (self->display, self); + gst_wl_display_unregister_buffer (self->display, self->gstbuffer); G_OBJECT_CLASS (gst_wl_buffer_parent_class)->dispose (gobject); } @@ -150,7 +148,6 @@ static void gstbuffer_disposed (GstWlBuffer * self) { g_assert (!self->used_by_compositor); - self->gstbuffer = NULL; GST_TRACE_OBJECT (self, "owning GstBuffer was finalized"); @@ -170,25 +167,25 @@ gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, struct wl_buffer *wlbuffer, self->wlbuffer = wlbuffer; self->display = display; - gst_wl_display_register_buffer (self->display, self); + gst_wl_display_register_buffer (self->display, self->gstbuffer, self); wl_buffer_add_listener (self->wlbuffer, &buffer_listener, self); - gst_mini_object_set_qdata ((GstMiniObject *) gstbuffer, - gst_wl_buffer_qdata_quark (), self, (GDestroyNotify) gstbuffer_disposed); + gst_mini_object_weak_ref (GST_MINI_OBJECT (gstbuffer), + (GstMiniObjectNotify) gstbuffer_disposed, self); + return self; } GstWlBuffer * -gst_buffer_get_wl_buffer (GstBuffer * gstbuffer) +gst_buffer_get_wl_buffer (GstWlDisplay * display, GstBuffer * gstbuffer) { - return gst_mini_object_get_qdata ((GstMiniObject *) gstbuffer, - gst_wl_buffer_qdata_quark ()); + return gst_wl_display_lookup_buffer (display, gstbuffer); } void -gst_wl_buffer_force_release_and_unref (GstWlBuffer * self) +gst_wl_buffer_force_release_and_unref (GstBuffer * buf, GstWlBuffer * self) { /* Force a buffer release. * At this point, the GstWlDisplay has killed its event loop, @@ -212,6 +209,7 @@ gst_wl_buffer_force_release_and_unref (GstWlBuffer * self) wl_buffer_destroy (self->wlbuffer); self->wlbuffer = NULL; self->display = NULL; + self->gstbuffer = NULL; /* remove the reference that the caller (GstWlDisplay) owns */ g_object_unref (self); diff --git a/ext/wayland/wlbuffer.h b/ext/wayland/wlbuffer.h index cbb50f719a..5bd25168c8 100644 --- a/ext/wayland/wlbuffer.h +++ b/ext/wayland/wlbuffer.h @@ -56,9 +56,9 @@ GType gst_wl_buffer_get_type (void); GstWlBuffer * gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, struct wl_buffer * wlbuffer, GstWlDisplay * display); -GstWlBuffer * gst_buffer_get_wl_buffer (GstBuffer * gstbuffer); +GstWlBuffer * gst_buffer_get_wl_buffer (GstWlDisplay * display, GstBuffer * gstbuffer); -void gst_wl_buffer_force_release_and_unref (GstWlBuffer * self); +void gst_wl_buffer_force_release_and_unref (GstBuffer *buf, GstWlBuffer * self); void gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface); diff --git a/ext/wayland/wldisplay.c b/ext/wayland/wldisplay.c index f7115d59f5..649ce7a9a5 100644 --- a/ext/wayland/wldisplay.c +++ b/ext/wayland/wldisplay.c @@ -52,6 +52,12 @@ gst_wl_display_init (GstWlDisplay * self) g_mutex_init (&self->buffers_mutex); } +static void +gst_wl_ref_wl_buffer (gpointer key, gpointer value, gpointer user_data) +{ + g_object_ref (value); +} + static void gst_wl_display_finalize (GObject * gobject) { @@ -65,7 +71,7 @@ gst_wl_display_finalize (GObject * gobject) * at the same time, take their ownership */ g_mutex_lock (&self->buffers_mutex); self->shutting_down = TRUE; - g_hash_table_foreach (self->buffers, (GHFunc) g_object_ref, NULL); + g_hash_table_foreach (self->buffers, gst_wl_ref_wl_buffer, NULL); g_mutex_unlock (&self->buffers_mutex); g_hash_table_foreach (self->buffers, @@ -379,24 +385,36 @@ gst_wl_display_new_existing (struct wl_display * display, } void -gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf) +gst_wl_display_register_buffer (GstWlDisplay * self, gpointer gstbuffer, + gpointer wlbuffer) { g_assert (!self->shutting_down); - GST_TRACE_OBJECT (self, "registering GstWlBuffer %p", buf); + GST_TRACE_OBJECT (self, "registering GstWlBuffer %p to GstBuffer %p", + wlbuffer, gstbuffer); g_mutex_lock (&self->buffers_mutex); - g_hash_table_add (self->buffers, buf); + g_hash_table_replace (self->buffers, gstbuffer, wlbuffer); g_mutex_unlock (&self->buffers_mutex); } +gpointer +gst_wl_display_lookup_buffer (GstWlDisplay * self, gpointer gstbuffer) +{ + gpointer wlbuffer; + g_mutex_lock (&self->buffers_mutex); + wlbuffer = g_hash_table_lookup (self->buffers, gstbuffer); + g_mutex_unlock (&self->buffers_mutex); + return wlbuffer; +} + void -gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf) +gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer gstbuffer) { - GST_TRACE_OBJECT (self, "unregistering GstWlBuffer %p", buf); + GST_TRACE_OBJECT (self, "unregistering GstWlBuffer owned by %p", gstbuffer); g_mutex_lock (&self->buffers_mutex); if (G_LIKELY (!self->shutting_down)) - g_hash_table_remove (self->buffers, buf); + g_hash_table_remove (self->buffers, gstbuffer); g_mutex_unlock (&self->buffers_mutex); } diff --git a/ext/wayland/wldisplay.h b/ext/wayland/wldisplay.h index 4ecc0d6593..8ce9858fae 100644 --- a/ext/wayland/wldisplay.h +++ b/ext/wayland/wldisplay.h @@ -85,8 +85,10 @@ GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display, gboolean take_ownership, GError ** error); /* see wlbuffer.c for explanation */ -void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf); -void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf); +void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer gstbuffer, + gpointer wlbuffer); +void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer gstbuffer); +gpointer gst_wl_display_lookup_buffer (GstWlDisplay * self, gpointer gstbuffer); gboolean gst_wl_display_check_format_for_shm (GstWlDisplay * display, GstVideoFormat format);