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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5176>
This commit is contained in:
Seungha Yang 2023-08-12 00:58:10 +09:00 committed by GStreamer Marge Bot
parent 815b1dfb4a
commit c992dd2184

View file

@ -21,6 +21,7 @@
#include <string.h>
#include <mfapi.h>
#include <wrl.h>
#include <memory>
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<GstWasapi2RingBufferPtr> 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<GstWasapi2RingBufferPtr> listener_;
gboolean loopback_;
};
struct GstWasapi2RingBufferPrivate
{
std::shared_ptr<GstWasapi2RingBufferPtr> 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);
}