d3d11screencapturesrc: Use DirectXMath struct and C++ mutex

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5572>
This commit is contained in:
Seungha Yang 2023-10-27 22:23:46 +09:00
parent 63bb0b8de7
commit e13612162b

View file

@ -49,69 +49,36 @@
#include "gstd3d11dxgicapture.h" #include "gstd3d11dxgicapture.h"
#include "gstd3d11pluginutils.h" #include "gstd3d11pluginutils.h"
#include <string.h> #include <string.h>
#include <mutex>
#include <wrl.h> #include <wrl.h>
#define _XM_NO_INTRINSICS_
#include <DirectXMath.h>
GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_screen_capture_debug); GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_screen_capture_debug);
#define GST_CAT_DEFAULT gst_d3d11_screen_capture_debug #define GST_CAT_DEFAULT gst_d3d11_screen_capture_debug
/* *INDENT-OFF* */ /* *INDENT-OFF* */
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
using namespace DirectX;
/* List of GstD3D11DxgiCapture weakref */ /* List of GstD3D11DxgiCapture weakref */
G_LOCK_DEFINE_STATIC (dupl_list_lock); static std::mutex dupl_list_lock;
static GList *dupl_list = nullptr; static GList *dupl_list = nullptr;
/* Below implemenation were taken from Microsoft sample /* Below implementation were taken from Microsoft sample
* https://github.com/microsoft/Windows-classic-samples/tree/master/Samples/DXGIDesktopDuplication * https://github.com/microsoft/Windows-classic-samples/tree/master/Samples/DXGIDesktopDuplication
*/ */
#define NUMVERTICES 6 #define NUMVERTICES 6
#define BPP 4 #define BPP 4
/* Define our own MyFLOAT3 and MyFLOAT2 struct, since MinGW doesn't support struct VERTEX
* DirectXMath.h
*/
struct MyFLOAT3
{ {
float x; XMFLOAT3 Pos;
float y; XMFLOAT2 TexCoord;
float z;
MyFLOAT3() = default;
MyFLOAT3(const MyFLOAT3&) = default;
MyFLOAT3& operator=(const MyFLOAT3&) = default;
MyFLOAT3(MyFLOAT3&&) = default;
MyFLOAT3& operator=(MyFLOAT3&&) = default;
constexpr MyFLOAT3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
explicit MyFLOAT3(const float *pArray) : x(pArray[0]), y(pArray[1]), z(pArray[2]) {}
}; };
struct MyFLOAT2
{
float x;
float y;
MyFLOAT2() = default;
MyFLOAT2(const MyFLOAT2&) = default;
MyFLOAT2& operator=(const MyFLOAT2&) = default;
MyFLOAT2(MyFLOAT2&&) = default;
MyFLOAT2& operator=(MyFLOAT2&&) = default;
constexpr MyFLOAT2(float _x, float _y) : x(_x), y(_y) {}
explicit MyFLOAT2(const float *pArray) : x(pArray[0]), y(pArray[1]) {}
};
typedef struct
{
MyFLOAT3 Pos;
MyFLOAT2 TexCoord;
} VERTEX;
/* List of expected error cases */ /* List of expected error cases */
/* These are the errors we expect from general Dxgi API due to a transition */ /* These are the errors we expect from general Dxgi API due to a transition */
HRESULT SystemTransitionsExpectedErrors[] = { HRESULT SystemTransitionsExpectedErrors[] = {
@ -387,12 +354,12 @@ public:
VERTEX Vertices[NUMVERTICES] = VERTEX Vertices[NUMVERTICES] =
{ {
{MyFLOAT3(-1.0f, -1.0f, 0), MyFLOAT2(0.0f, 1.0f)}, {XMFLOAT3(-1.0f, -1.0f, 0), XMFLOAT2(0.0f, 1.0f)},
{MyFLOAT3(-1.0f, 1.0f, 0), MyFLOAT2(0.0f, 0.0f)}, {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)},
{MyFLOAT3(1.0f, -1.0f, 0), MyFLOAT2(1.0f, 1.0f)}, {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)},
{MyFLOAT3(1.0f, -1.0f, 0), MyFLOAT2(1.0f, 1.0f)}, {XMFLOAT3(1.0f, -1.0f, 0), XMFLOAT2(1.0f, 1.0f)},
{MyFLOAT3(-1.0f, 1.0f, 0), MyFLOAT2(0.0f, 0.0f)}, {XMFLOAT3(-1.0f, 1.0f, 0), XMFLOAT2(0.0f, 0.0f)},
{MyFLOAT3(1.0f, 1.0f, 0), MyFLOAT2(1.0f, 0.0f)}, {XMFLOAT3(1.0f, 1.0f, 0), XMFLOAT2(1.0f, 0.0f)},
}; };
D3D11_TEXTURE2D_DESC FullDesc; D3D11_TEXTURE2D_DESC FullDesc;
@ -1030,16 +997,16 @@ private:
DestDirty.bottom = Dirty->right; DestDirty.bottom = Dirty->right;
Vertices[0].TexCoord = Vertices[0].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[1].TexCoord = Vertices[1].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[2].TexCoord = Vertices[2].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[5].TexCoord = Vertices[5].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
break; break;
case DXGI_MODE_ROTATION_ROTATE180: case DXGI_MODE_ROTATION_ROTATE180:
@ -1049,16 +1016,16 @@ private:
DestDirty.bottom = Height - Dirty->top; DestDirty.bottom = Height - Dirty->top;
Vertices[0].TexCoord = Vertices[0].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[1].TexCoord = Vertices[1].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[2].TexCoord = Vertices[2].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[5].TexCoord = Vertices[5].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
break; break;
case DXGI_MODE_ROTATION_ROTATE270: case DXGI_MODE_ROTATION_ROTATE270:
@ -1068,56 +1035,56 @@ private:
DestDirty.bottom = Height - Dirty->left; DestDirty.bottom = Height - Dirty->left;
Vertices[0].TexCoord = Vertices[0].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[1].TexCoord = Vertices[1].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[2].TexCoord = Vertices[2].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[5].TexCoord = Vertices[5].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
break; break;
case DXGI_MODE_ROTATION_UNSPECIFIED: case DXGI_MODE_ROTATION_UNSPECIFIED:
case DXGI_MODE_ROTATION_IDENTITY: case DXGI_MODE_ROTATION_IDENTITY:
default: default:
Vertices[0].TexCoord = Vertices[0].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[1].TexCoord = Vertices[1].TexCoord =
MyFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->left / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
Vertices[2].TexCoord = Vertices[2].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height)); Dirty->bottom / static_cast<FLOAT>(ThisDesc->Height));
Vertices[5].TexCoord = Vertices[5].TexCoord =
MyFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width), XMFLOAT2(Dirty->right / static_cast<FLOAT>(ThisDesc->Width),
Dirty->top / static_cast<FLOAT>(ThisDesc->Height)); Dirty->top / static_cast<FLOAT>(ThisDesc->Height));
break; break;
} }
/* Set positions */ /* Set positions */
Vertices[0].Pos = Vertices[0].Pos =
MyFLOAT3( XMFLOAT3(
(DestDirty.left - CenterX) / static_cast<FLOAT>(CenterX), (DestDirty.left - CenterX) / static_cast<FLOAT>(CenterX),
-1 * (DestDirty.bottom - CenterY) / static_cast<FLOAT>(CenterY), -1 * (DestDirty.bottom - CenterY) / static_cast<FLOAT>(CenterY),
0.0f); 0.0f);
Vertices[1].Pos = Vertices[1].Pos =
MyFLOAT3( XMFLOAT3(
(DestDirty.left - CenterX) / static_cast<FLOAT>(CenterX), (DestDirty.left - CenterX) / static_cast<FLOAT>(CenterX),
-1 * (DestDirty.top - CenterY) / static_cast<FLOAT>(CenterY), -1 * (DestDirty.top - CenterY) / static_cast<FLOAT>(CenterY),
0.0f); 0.0f);
Vertices[2].Pos = Vertices[2].Pos =
MyFLOAT3( XMFLOAT3(
(DestDirty.right - CenterX) / static_cast<FLOAT>(CenterX), (DestDirty.right - CenterX) / static_cast<FLOAT>(CenterX),
-1 * (DestDirty.bottom - CenterY) / static_cast<FLOAT>(CenterY), -1 * (DestDirty.bottom - CenterY) / static_cast<FLOAT>(CenterY),
0.0f); 0.0f);
Vertices[3].Pos = Vertices[2].Pos; Vertices[3].Pos = Vertices[2].Pos;
Vertices[4].Pos = Vertices[1].Pos; Vertices[4].Pos = Vertices[1].Pos;
Vertices[5].Pos = Vertices[5].Pos =
MyFLOAT3( XMFLOAT3(
(DestDirty.right - CenterX) / static_cast<FLOAT>(CenterX), (DestDirty.right - CenterX) / static_cast<FLOAT>(CenterX),
-1 * (DestDirty.top - CenterY) / static_cast<FLOAT>(CenterY), -1 * (DestDirty.top - CenterY) / static_cast<FLOAT>(CenterY),
0.0f); 0.0f);
@ -1707,9 +1674,8 @@ static void
gst_d3d11_dxgi_capture_weak_ref_notify (gpointer data, gst_d3d11_dxgi_capture_weak_ref_notify (gpointer data,
GstD3D11DxgiCapture * dupl) GstD3D11DxgiCapture * dupl)
{ {
G_LOCK (dupl_list_lock); std::lock_guard < std::mutex > lk (dupl_list_lock);
dupl_list = g_list_remove (dupl_list, dupl); dupl_list = g_list_remove (dupl_list, dupl);
G_UNLOCK (dupl_list_lock);
} }
GstD3D11ScreenCapture * GstD3D11ScreenCapture *
@ -1727,30 +1693,24 @@ gst_d3d11_dxgi_capture_new (GstD3D11Device * device, HMONITOR monitor_handle)
* See also * See also
* https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgioutput1-duplicateoutput#remarks * https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgioutput1-duplicateoutput#remarks
*/ */
G_LOCK (dupl_list_lock); std::lock_guard < std::mutex > lk (dupl_list_lock);
for (iter = dupl_list; iter; iter = g_list_next (iter)) { for (iter = dupl_list; iter; iter = g_list_next (iter)) {
GstD3D11DxgiCapture *dupl = (GstD3D11DxgiCapture *) iter->data; GstD3D11DxgiCapture *dupl = (GstD3D11DxgiCapture *) iter->data;
if (dupl->monitor_handle == monitor_handle) { if (dupl->monitor_handle == monitor_handle) {
GST_DEBUG ("Found configured desktop dup object for monitor handle %p", GST_DEBUG ("Found configured desktop dup object for monitor handle %p",
monitor_handle); monitor_handle);
self = (GstD3D11DxgiCapture *) gst_object_ref (dupl); gst_object_ref (dupl);
break; return GST_D3D11_SCREEN_CAPTURE_CAST (dupl);
} }
} }
if (self) {
G_UNLOCK (dupl_list_lock);
return GST_D3D11_SCREEN_CAPTURE_CAST (self);
}
self = (GstD3D11DxgiCapture *) g_object_new (GST_TYPE_D3D11_DXGI_CAPTURE, self = (GstD3D11DxgiCapture *) g_object_new (GST_TYPE_D3D11_DXGI_CAPTURE,
"d3d11device", device, "monitor-handle", monitor_handle, nullptr); "d3d11device", device, "monitor-handle", monitor_handle, nullptr);
if (!self->device) { if (!self->device) {
GST_WARNING_OBJECT (self, "Couldn't configure desktop dup object"); GST_WARNING_OBJECT (self, "Couldn't configure desktop dup object");
gst_object_unref (self); gst_object_unref (self);
G_UNLOCK (dupl_list_lock);
return nullptr; return nullptr;
} }
@ -1759,8 +1719,6 @@ gst_d3d11_dxgi_capture_new (GstD3D11Device * device, HMONITOR monitor_handle)
(GWeakNotify) gst_d3d11_dxgi_capture_weak_ref_notify, nullptr); (GWeakNotify) gst_d3d11_dxgi_capture_weak_ref_notify, nullptr);
dupl_list = g_list_append (dupl_list, self); dupl_list = g_list_append (dupl_list, self);
G_UNLOCK (dupl_list_lock);
return GST_D3D11_SCREEN_CAPTURE_CAST (self); return GST_D3D11_SCREEN_CAPTURE_CAST (self);
} }