diff --git a/sys/d3dvideosink/d3dhelpers.c b/sys/d3dvideosink/d3dhelpers.c index 80811aa283..3e4bbcc848 100644 --- a/sys/d3dvideosink/d3dhelpers.c +++ b/sys/d3dvideosink/d3dhelpers.c @@ -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); diff --git a/sys/d3dvideosink/d3dvideosink.h b/sys/d3dvideosink/d3dvideosink.h index 67ac6c01c4..807f3be720 100644 --- a/sys/d3dvideosink/d3dvideosink.h +++ b/sys/d3dvideosink/d3dvideosink.h @@ -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 { \