d3d11device: raise 'device-removed' signal on DXGI_ERROR_DEVICE_REMOVED

When this error gets caught the GstD3D11Device object raises the new
"device-removed" signal. This allows to handle the error from outside:
stop the playback, re-create the player, replace the catched GstContext by
the new one.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6193>
This commit is contained in:
Alexander Slobodeniuk 2024-02-23 00:24:14 +01:00 committed by GStreamer Marge Bot
parent a4aa9e197e
commit 6a6a4bf1a4
3 changed files with 46 additions and 0 deletions

View file

@ -81,5 +81,8 @@ GST_D3D11_API
HRESULT gst_d3d11_device_get_rasterizer_msaa (GstD3D11Device * device,
ID3D11RasterizerState ** rasterizer);
/* Used internally by gstd3d11utils.cpp */
void gst_d3d11_device_mark_removed (GstD3D11Device * device, HRESULT reason);
G_END_DECLS

View file

@ -101,6 +101,16 @@ enum
#define DEFAULT_ADAPTER 0
#define DEFAULT_CREATE_FLAGS 0
enum
{
/* signals */
SIGNAL_DEVICE_REMOVED,
LAST_SIGNAL
};
static guint gst_d3d11_device_signals[LAST_SIGNAL] = { 0, };
/* *INDENT-OFF* */
struct _GstD3D11DevicePrivate
{
@ -146,6 +156,8 @@ struct _GstD3D11DevicePrivate
IDXGIDebug *dxgi_debug = nullptr;
IDXGIInfoQueue *dxgi_info_queue = nullptr;
#endif
gboolean device_removed = FALSE;
};
/* *INDENT-ON* */
@ -417,6 +429,20 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
"DXGI Adapter LUID (Locally Unique Identifier) of created device",
G_MININT64, G_MAXINT64, 0, readable_flags));
/**
* GstD3D11Device::device-removed:
* @device: the #d3d11device
*
* Emitted when the D3D11Device gets suspended by the DirectX (error
* DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET have been returned
* after one of the DirectX operations).
*
* Since: 1.26
*/
gst_d3d11_device_signals[SIGNAL_DEVICE_REMOVED] =
g_signal_new ("device-removed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
gst_d3d11_memory_init_once ();
}
@ -1396,6 +1422,18 @@ gst_d3d11_device_get_format (GstD3D11Device * device, GstVideoFormat format,
return TRUE;
}
void
gst_d3d11_device_mark_removed (GstD3D11Device * device, HRESULT reason)
{
g_return_if_fail (GST_IS_D3D11_DEVICE (device));
if (!device->priv->device_removed) {
g_signal_emit (device, gst_d3d11_device_signals[SIGNAL_DEVICE_REMOVED], 0,
reason);
device->priv->device_removed = TRUE;
}
}
GST_DEFINE_MINI_OBJECT_TYPE (GstD3D11Fence, gst_d3d11_fence);
struct _GstD3D11FencePrivate

View file

@ -24,6 +24,7 @@
#include "gstd3d11utils.h"
#include "gstd3d11device.h"
#include "gstd3d11-private.h"
#include "gstd3d11device-private.h"
#include <windows.h>
#include <versionhelpers.h>
@ -561,6 +562,9 @@ gst_d3d11_log_gpu_remove_reason (HRESULT hr, GstD3D11Device * device,
gst_debug_log (cat, GST_LEVEL_ERROR, file, function, line,
NULL, "DeviceRemovedReason: 0x%x, %s", (guint) hr,
GST_STR_NULL (error_text));
if (hr != DXGI_ERROR_DEVICE_REMOVED)
g_critical ("D3D11Device have been removed. Reason (0x%x): %s",
(guint) hr, GST_STR_NULL (error_text));
g_free (error_text);
gst_d3d11_device_log_live_objects (device, file, function, line);
@ -606,6 +610,7 @@ _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
hr = device_handle->GetDeviceRemovedReason ();
if (hr != S_OK) {
gst_d3d11_log_gpu_remove_reason (hr, device, cat, file, function, line);
gst_d3d11_device_mark_removed (device, hr);
}
}