QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GstD3D11ContextBridge.cc
Go to the documentation of this file.
4
5#if defined(Q_OS_WIN) && defined(QGC_HAS_GST_D3D11_GPU_PATH)
6
8
9#include <QtCore/QMutexLocker>
10
11#include <QtGui/rhi/qrhi.h>
12#include <QtGui/rhi/qrhi_platform.h>
13
14#include <gst/d3d11/gstd3d11.h>
15
16QGC_LOGGING_CATEGORY(GstD3D11BridgeLog, "Video.GStreamer.HwBuffers.GstD3D11Bridge")
17
18namespace GstD3D11ContextBridge {
19namespace {
20
21GstD3DContextBridgeCommon::BridgeState s_state;
22GstD3D11Device *s_device = nullptr;
23
24bool primeLocked()
25{
26 if (s_state.primed) return true;
27
28 QRhi *rhi = GstD3DContextBridgeCommon::checkRhiBackend(
29 s_state, GstD3D11BridgeLog(), int(QRhi::D3D11), "D3D11");
30 if (!rhi) return false;
31
32 auto *handles = static_cast<const QRhiD3D11NativeHandles *>(rhi->nativeHandles());
33 if (!handles || !handles->dev) {
34 qCWarning(GstD3D11BridgeLog) << "QRhiD3D11NativeHandles missing ID3D11Device*";
35 return false;
36 }
37
38 // gst_d3d11_device_new_wrapped (renamed from gst_d3d11_device_wrap in 1.28): shared device keeps textures sampleable by QRhi without keyed-mutex transfer.
39 s_device = gst_d3d11_device_new_wrapped(static_cast<ID3D11Device *>(handles->dev));
40 if (!s_device) {
41 qCWarning(GstD3D11BridgeLog) << "gst_d3d11_device_new_wrapped failed";
42 return false;
43 }
44 s_state.primed = true;
45 qCInfo(GstD3D11BridgeLog) << "D3D11 bridge primed: shared device =" << s_device;
46 // Sign-extend qint32 HighPart so it matches LARGE_INTEGER::QuadPart bit-for-bit.
47 const gint64 expectedLuid = (static_cast<gint64>(handles->adapterLuidHigh) << 32)
48 | (static_cast<gint64>(handles->adapterLuidLow) & 0xFFFFFFFFLL);
49 GstD3DContextBridgeCommon::logAdapterMatch(rhi, expectedLuid, s_device,
50 GstD3D11BridgeLog(), "D3D11");
51 return true;
52}
53
54} // namespace
55
56bool prime()
57{
58 QMutexLocker lock(&s_state.mutex);
59 return primeLocked();
60}
61
62GstD3D11Device *currentDevice()
63{
64 QMutexLocker lock(&s_state.mutex);
65 if (!s_device) return nullptr;
66 return GST_D3D11_DEVICE_CAST(gst_object_ref(s_device));
67}
68
69GstBusSyncReply handleSyncMessage(GstMessage *message)
70{
71 GstElement *element = GstD3DContextBridgeCommon::matchNeedContext(
72 message, GST_D3D11_DEVICE_HANDLE_CONTEXT_TYPE);
73 if (!element) {
74 return GST_BUS_PASS;
75 }
76
77 QMutexLocker lock(&s_state.mutex);
78 if (!primeLocked() || !s_device) {
79 return GST_BUS_PASS;
80 }
81
82 // gst_d3d11_context_new wraps s_device in a GstContext; gst_object_ref's s_device internally.
83 GstContext *ctx = gst_d3d11_context_new(s_device);
84 if (!ctx) {
85 qCWarning(GstD3D11BridgeLog) << "gst_d3d11_context_new failed for element"
86 << GST_ELEMENT_NAME(element);
87 return GST_BUS_PASS;
88 }
89 gst_element_set_context(element, ctx);
90 gst_context_unref(ctx);
91 gst_message_unref(message);
92 GstD3DContextBridgeCommon::logHandoff(s_state, GstD3D11BridgeLog(), element, "D3D11");
93 return GST_BUS_DROP;
94}
95
96void reset()
97{
98 QMutexLocker lock(&s_state.mutex);
99 gst_clear_object(&s_device);
100 s_state.primed = false;
101 s_state.warnedWrongBackend = false;
102 qCDebug(GstD3D11BridgeLog) << "D3D11 bridge reset";
103}
104
105namespace {
106struct D3D11BridgeRegistrar {
107 D3D11BridgeRegistrar() {
108 GstContextBridgeRegistry::registerBridgeHandler(&GstD3D11ContextBridge::handleSyncMessage);
109 GstContextBridgeRegistry::registerResetCallback(&GstD3D11ContextBridge::reset);
110 }
111};
112static D3D11BridgeRegistrar s_d3d11BridgeRegistrar;
113} // anonymous namespace
114
115} // namespace GstD3D11ContextBridge
116
117#endif // Q_OS_WIN && QGC_HAS_GST_D3D11_GPU_PATH
struct _GstElement GstElement
#define QGC_LOGGING_CATEGORY(name, categoryStr)