mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
d3dvideosink: use thread pool to handle events from hidden window event queue
window event queue now does not lock on the class lock, so we can now shut it down without releasing the class lock, thus avoiding a potential race when stopping the sink.
This commit is contained in:
parent
027eb5ef20
commit
eff0117b5a
2 changed files with 59 additions and 10 deletions
|
@ -57,6 +57,8 @@ static void d3d_class_notify_device_lost (GstD3DVideoSink * sink);
|
|||
static void d3d_class_display_device_destroy (GstD3DVideoSinkClass * klass);
|
||||
static gboolean d3d_class_display_device_create (GstD3DVideoSinkClass * klass,
|
||||
UINT adapter);
|
||||
static void d3d_class_hidden_window_message_queue (gpointer data,
|
||||
gpointer user_data);
|
||||
|
||||
static LRESULT APIENTRY d3d_wnd_proc_internal (HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
|
@ -72,6 +74,12 @@ static gint WM_D3DVIDEO_NOTIFY_DEVICE_LOST = 0;
|
|||
|
||||
#define WM_QUIT_THREAD WM_USER+0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint window_message_id;
|
||||
guint create_count;
|
||||
} GstD3DVideoSinkEvent;
|
||||
|
||||
/* Helpers */
|
||||
|
||||
#define ERROR_CHECK_HR(hr) \
|
||||
|
@ -2666,7 +2674,13 @@ static void
|
|||
d3d_class_notify_device_lost (GstD3DVideoSink * sink)
|
||||
{
|
||||
GstD3DVideoSinkClass *klass = GST_D3DVIDEOSINK_GET_CLASS (sink);
|
||||
PostMessage (klass->d3d.hidden_window, WM_D3DVIDEO_NOTIFY_DEVICE_LOST, 0, 0);
|
||||
GstD3DVideoSinkEvent *evt = g_new0 (GstD3DVideoSinkEvent, 1);
|
||||
|
||||
evt->window_message_id = IDT_DEVICE_RESET_TIMER;
|
||||
evt->create_count = klass->create_count;
|
||||
gst_element_call_async (GST_ELEMENT (klass),
|
||||
(GstElementCallAsyncFunc) d3d_class_hidden_window_message_queue, evt,
|
||||
g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2734,29 +2748,61 @@ end:
|
|||
|
||||
/* Hidden Window Loop Thread */
|
||||
|
||||
static void
|
||||
d3d_class_hidden_window_message_queue (gpointer data, gpointer user_data)
|
||||
{
|
||||
guint id = 0;
|
||||
GstD3DVideoSinkClass *klass = (GstD3DVideoSinkClass *) data;
|
||||
GstD3DVideoSinkEvent *evt = (GstD3DVideoSinkEvent *) user_data;
|
||||
|
||||
if (!klass || !evt)
|
||||
return;
|
||||
|
||||
switch (evt->window_message_id) {
|
||||
case IDT_DEVICE_RESET_TIMER:
|
||||
LOCK_CLASS (NULL, klass);
|
||||
/* make sure this event does not originate from old class */
|
||||
if (evt->create_count == klass->create_count)
|
||||
d3d_class_reset_display_device (klass);
|
||||
UNLOCK_CLASS (NULL, klass);
|
||||
break;
|
||||
default:
|
||||
if (id == WM_D3DVIDEO_NOTIFY_DEVICE_LOST) {
|
||||
LOCK_CLASS (NULL, klass);
|
||||
/* make sure this event does not originate from old class */
|
||||
if (evt->create_count == klass->create_count)
|
||||
d3d_class_notify_device_lost_all (klass);
|
||||
UNLOCK_CLASS (NULL, klass);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT APIENTRY
|
||||
D3DHiddenWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
GstD3DVideoSinkClass *klass =
|
||||
(GstD3DVideoSinkClass *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
|
||||
GstD3DVideoSinkEvent *evt;
|
||||
|
||||
switch (message) {
|
||||
case WM_TIMER:
|
||||
switch (wParam) {
|
||||
case IDT_DEVICE_RESET_TIMER:
|
||||
d3d_class_reset_display_device ((GstD3DVideoSinkClass *)
|
||||
GetWindowLongPtr (hWnd, GWLP_USERDATA));
|
||||
evt = g_new0 (GstD3DVideoSinkEvent, 1);
|
||||
evt->window_message_id = IDT_DEVICE_RESET_TIMER;
|
||||
evt->create_count = klass->create_count;
|
||||
gst_element_call_async (GST_ELEMENT (klass),
|
||||
(GstElementCallAsyncFunc) d3d_class_hidden_window_message_queue,
|
||||
evt, g_free);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage (0);
|
||||
return 0;
|
||||
default:
|
||||
/* non constants */
|
||||
if (message == WM_D3DVIDEO_NOTIFY_DEVICE_LOST) {
|
||||
d3d_class_notify_device_lost_all ((GstD3DVideoSinkClass *)
|
||||
GetWindowLongPtr (hWnd, GWLP_USERDATA));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc (hWnd, message, wParam, lParam);
|
||||
|
|
|
@ -74,6 +74,9 @@ struct _GstD3DVideoSinkClass
|
|||
GstVideoSinkClass parent_class;
|
||||
GstD3DDataClass d3d;
|
||||
GRecMutex lock;
|
||||
/* this count is incremented each time the sink is destroyed, so that
|
||||
* old queue events can be ignored */
|
||||
guint create_count;
|
||||
};
|
||||
|
||||
#define LOCK_SINK(sink) G_STMT_START { \
|
||||
|
|
Loading…
Reference in a new issue