From c992dd2184b986fab2c2888bbe5197a6d7366300 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 12 Aug 2023 00:58:10 +0900 Subject: [PATCH] wasapi2ringbuffer: Don't use GLib's weak pointer implementation GWeakRef takes global mutex. Use C++ weak_ptr which will perform atomic operation internally. Part-of: --- .../sys/wasapi2/gstwasapi2ringbuffer.cpp | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/wasapi2/gstwasapi2ringbuffer.cpp b/subprojects/gst-plugins-bad/sys/wasapi2/gstwasapi2ringbuffer.cpp index 8069d333a0..f60eca9542 100644 --- a/subprojects/gst-plugins-bad/sys/wasapi2/gstwasapi2ringbuffer.cpp +++ b/subprojects/gst-plugins-bad/sys/wasapi2/gstwasapi2ringbuffer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include GST_DEBUG_CATEGORY_STATIC (gst_wasapi2_ring_buffer_debug); #define GST_CAT_DEFAULT gst_wasapi2_ring_buffer_debug @@ -32,22 +33,28 @@ gst_wasapi2_ring_buffer_loopback_callback (GstWasapi2RingBuffer * buf); /* *INDENT-OFF* */ using namespace Microsoft::WRL; +struct GstWasapi2RingBufferPtr +{ + GstWasapi2RingBufferPtr (GstWasapi2RingBuffer * ringbuffer) + : obj(ringbuffer) + { + } + + /* Point to ringbuffer without holding ownership */ + GstWasapi2RingBuffer *obj; +}; + class GstWasapiAsyncCallback : public IMFAsyncCallback { public: - GstWasapiAsyncCallback(GstWasapi2RingBuffer *listener, + GstWasapiAsyncCallback(std::shared_ptr listener, DWORD queue_id, gboolean loopback) : ref_count_(1) , queue_id_(queue_id) + , listener_(listener) , loopback_(loopback) { - g_weak_ref_init (&listener_, listener); - } - - virtual ~GstWasapiAsyncCallback () - { - g_weak_ref_set (&listener_, nullptr); } /* IUnknown */ @@ -108,20 +115,18 @@ public: STDMETHODIMP Invoke(IMFAsyncResult * pAsyncResult) { - GstWasapi2RingBuffer *ringbuffer; HRESULT hr; + auto ptr = listener_.lock (); - ringbuffer = (GstWasapi2RingBuffer *) g_weak_ref_get (&listener_); - if (!ringbuffer) { + if (!ptr) { GST_WARNING ("Listener was removed"); return S_OK; } if (loopback_) - hr = gst_wasapi2_ring_buffer_loopback_callback (ringbuffer); + hr = gst_wasapi2_ring_buffer_loopback_callback (ptr->obj); else - hr = gst_wasapi2_ring_buffer_io_callback (ringbuffer); - gst_object_unref (ringbuffer); + hr = gst_wasapi2_ring_buffer_io_callback (ptr->obj); return hr; } @@ -129,9 +134,14 @@ public: private: ULONG ref_count_; DWORD queue_id_; - GWeakRef listener_; + std::weak_ptr listener_; gboolean loopback_; }; + +struct GstWasapi2RingBufferPrivate +{ + std::shared_ptr obj_ptr; +}; /* *INDENT-ON* */ struct _GstWasapi2RingBuffer @@ -179,6 +189,8 @@ struct _GstWasapi2RingBuffer gboolean monitor_device_mute; GstCaps *supported_caps; + + GstWasapi2RingBufferPrivate *priv; }; static void gst_wasapi2_ring_buffer_constructed (GObject * object); @@ -239,6 +251,9 @@ gst_wasapi2_ring_buffer_init (GstWasapi2RingBuffer * self) self->event_handle = CreateEvent (nullptr, FALSE, FALSE, nullptr); self->loopback_event_handle = CreateEvent (nullptr, FALSE, FALSE, nullptr); g_mutex_init (&self->volume_lock); + + self->priv = new GstWasapi2RingBufferPrivate (); + self->priv->obj_ptr = std::make_shared < GstWasapi2RingBufferPtr > (self); } static void @@ -255,7 +270,8 @@ gst_wasapi2_ring_buffer_constructed (GObject * object) goto out; } - self->callback_object = new GstWasapiAsyncCallback (self, queue_id, FALSE); + self->callback_object = new GstWasapiAsyncCallback (self->priv->obj_ptr, + queue_id, FALSE); hr = MFCreateAsyncResult (nullptr, self->callback_object, nullptr, &self->callback_result); if (!gst_wasapi2_result (hr)) { @@ -265,7 +281,7 @@ gst_wasapi2_ring_buffer_constructed (GObject * object) /* Create another callback object for loopback silence feed */ self->loopback_callback_object = - new GstWasapiAsyncCallback (self, queue_id, TRUE); + new GstWasapiAsyncCallback (self->priv->obj_ptr, queue_id, TRUE); hr = MFCreateAsyncResult (nullptr, self->loopback_callback_object, nullptr, &self->loopback_callback_result); if (!gst_wasapi2_result (hr)) { @@ -284,6 +300,8 @@ gst_wasapi2_ring_buffer_dispose (GObject * object) { GstWasapi2RingBuffer *self = GST_WASAPI2_RING_BUFFER (object); + self->priv->obj_ptr = nullptr; + GST_WASAPI2_CLEAR_COM (self->render_client); GST_WASAPI2_CLEAR_COM (self->capture_client); GST_WASAPI2_CLEAR_COM (self->volume_object); @@ -309,6 +327,8 @@ gst_wasapi2_ring_buffer_finalize (GObject * object) CloseHandle (self->loopback_event_handle); g_mutex_clear (&self->volume_lock); + delete self->priv; + G_OBJECT_CLASS (parent_class)->finalize (object); }