d3d11decoder: Do not use miniobject qdata
authorSeungha Yang <seungha@centricular.com>
Sun, 14 Aug 2022 15:22:14 +0000 (00:22 +0900)
committerSeungha Yang <seungha@centricular.com>
Sun, 14 Aug 2022 17:50:18 +0000 (02:50 +0900)
The miniobject qdata uses global mutex.
Use ID3D11DeviceChild::{Set,Get}PrivateData methods instead.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2885>

subprojects/gst-plugins-bad/sys/d3d11/gstd3d11decoder.cpp

index 2458dc4..ef591b9 100644 (file)
 #include "gstd3d11pluginutils.h"
 #include <string.h>
 #include <string>
+#include <wrl.h>
 
 #ifdef HAVE_WINMM
 #include <mmsystem.h>
 #endif
 
+/* *INDENT-OFF* */
+using namespace Microsoft::WRL;
+/* *INDENT-ON* */
+
 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_decoder_debug);
 #define GST_CAT_DEFAULT gst_d3d11_decoder_debug
 
@@ -123,6 +128,85 @@ static const GUID *profile_av1_list[] = {
   /* TODO: add more profile */
 };
 
+DEFINE_GUID (IID_GST_D3D11_DECODER_VIEW_DATA, 0xe1fd3e17, 0x1e33,
+    0x4198, 0x9e, 0x48, 0xdb, 0x01, 0x55, 0x2b, 0xf1, 0x78);
+
+/* *INDENT-OFF* */
+class IGstD3D11DecoderViewData: public IUnknown
+{
+public:
+  static HRESULT
+  CreateInstance (guint8 index, IGstD3D11DecoderViewData ** data)
+  {
+    IGstD3D11DecoderViewData *self;
+
+    self = new IGstD3D11DecoderViewData (index);
+    if (!self)
+      return E_OUTOFMEMORY;
+
+    *data = self;
+
+    return S_OK;
+  }
+
+  STDMETHODIMP_ (ULONG)
+  AddRef (void)
+  {
+    return InterlockedIncrement (&ref_count_);
+  }
+
+  STDMETHODIMP_ (ULONG)
+  Release (void)
+  {
+    ULONG ref_count;
+
+    ref_count = InterlockedDecrement (&ref_count_);
+
+    if (ref_count == 0)
+      delete this;
+
+    return ref_count;
+  }
+
+  STDMETHODIMP
+  QueryInterface (REFIID riid, void ** object)
+  {
+    if (riid == IID_IUnknown) {
+      *object = static_cast<IUnknown *>
+          (static_cast<IGstD3D11DecoderViewData *> (this));
+    } else if (riid == IID_GST_D3D11_DECODER_VIEW_DATA) {
+      *object = this;
+    } else {
+      *object = nullptr;
+      return E_NOINTERFACE;
+    }
+
+    AddRef ();
+
+    return S_OK;
+  }
+
+  guint8
+  GetViewIndex (void)
+  {
+    return index_;
+  }
+
+private:
+  IGstD3D11DecoderViewData (guint8 index) : index_(index), ref_count_(1)
+  {
+  }
+
+  virtual ~IGstD3D11DecoderViewData (void)
+  {
+  }
+
+private:
+  guint8 index_;
+  ULONG ref_count_;
+};
+/* *INDENT-ON* */
+
 enum
 {
   PROP_0,
@@ -380,24 +464,15 @@ gst_d3d11_decoder_is_configured (GstD3D11Decoder * decoder)
   return decoder->configured;
 }
 
-static GQuark
-gst_d3d11_decoder_view_id_quark (void)
-{
-  static GQuark id_quark = 0;
-
-  GST_D3D11_CALL_ONCE_BEGIN {
-    id_quark = g_quark_from_string ("GstD3D11DecoderViewId");
-  } GST_D3D11_CALL_ONCE_END;
-
-  return id_quark;
-}
-
 static gboolean
 gst_d3d11_decoder_ensure_output_view (GstD3D11Decoder * self,
     GstBuffer * buffer)
 {
   GstD3D11Memory *mem;
-  gpointer val = NULL;
+  ID3D11Resource *texture;
+  ComPtr < IGstD3D11DecoderViewData > data;
+  UINT size;
+  HRESULT hr;
 
   mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
   if (!gst_d3d11_memory_get_decoder_output_view (mem, self->video_device,
@@ -409,25 +484,26 @@ gst_d3d11_decoder_ensure_output_view (GstD3D11Decoder * self,
   if (!self->use_array_of_texture)
     return TRUE;
 
-  val = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
-      gst_d3d11_decoder_view_id_quark ());
-  if (!val) {
-    g_assert (self->next_view_id < 128);
-    g_assert (self->next_view_id > 0);
+  size = sizeof (IGstD3D11DecoderViewData *);
+
+  texture = gst_d3d11_memory_get_resource_handle (mem);
+  texture->GetPrivateData (IID_GST_D3D11_DECODER_VIEW_DATA,
+      &size, data.GetAddressOf ());
 
-    gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
-        gst_d3d11_decoder_view_id_quark (),
-        GUINT_TO_POINTER (self->next_view_id), NULL);
+  if (!data) {
+    g_assert (self->next_view_id < 127);
+
+    hr = IGstD3D11DecoderViewData::CreateInstance (self->next_view_id, &data);
+    g_assert (SUCCEEDED (hr));
+
+    texture->SetPrivateDataInterface (IID_GST_D3D11_DECODER_VIEW_DATA,
+        data.Get ());
 
     self->next_view_id++;
-    /* valid view range is [0, 126], but 0 is not used to here
-     * (it's NULL as well) */
-    self->next_view_id %= 128;
-    if (self->next_view_id == 0)
-      self->next_view_id = 1;
+    /* valid view range is [0, 126] */
+    self->next_view_id %= 127;
   }
 
-
   return TRUE;
 }
 
@@ -473,12 +549,10 @@ gst_d3d11_decoder_prepare_output_view_pool (GstD3D11Decoder * self)
   if (!self->use_array_of_texture) {
     alloc_params->desc[0].ArraySize = pool_size;
   } else {
-    /* Valid view id is [0, 126], but we will use [1, 127] range so that
-     * it can be used by qdata, because zero is equal to null */
-    self->next_view_id = 1;
+    self->next_view_id = 0;
 
-    /* our pool size can be increased as much as possbile */
-    pool_size = 0;
+    /* Valid view id range is [0, 126] */
+    pool_size = 127;
   }
 
   gst_video_alignment_reset (&align);
@@ -1367,18 +1441,22 @@ gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder,
 
   if (index) {
     if (decoder->use_array_of_texture) {
-      guint8 id;
-      gpointer val = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
-          gst_d3d11_decoder_view_id_quark ());
-      if (!val) {
-        GST_ERROR_OBJECT (decoder, "memory has no qdata");
-        return NULL;
-      }
+      ID3D11Resource *texture;
+      ComPtr < IGstD3D11DecoderViewData > data;
+      UINT size;
+
+      texture = gst_d3d11_memory_get_resource_handle (dmem);
+      size = sizeof (IGstD3D11DecoderViewData *);
+
+      texture->GetPrivateData (IID_GST_D3D11_DECODER_VIEW_DATA,
+          &size, data.GetAddressOf ());
 
-      id = (guint8) GPOINTER_TO_UINT (val);
-      g_assert (id < 128);
+      if (!data) {
+        GST_ERROR_OBJECT (decoder, "memory has no private data");
+        return nullptr;
+      }
 
-      *index = (id - 1);
+      *index = data->GetViewIndex ();
     } else {
       *index = gst_d3d11_memory_get_subresource_index (dmem);
     }