d3dvideosink: fix regression setting window handle in pause/play

https://bugzilla.gnome.org/show_bug.cgi?id=656905
This commit is contained in:
Carsten Kroll 2012-03-15 22:12:59 +01:00 committed by Tim-Philipp Müller
parent aca69cbf63
commit 6f3ea8e67b

View file

@ -63,7 +63,6 @@ struct _GstD3DVideoSinkHookData
static GstD3DVideoSinkShared shared; static GstD3DVideoSinkShared shared;
/* Define a shared lock to synchronize the creation/destruction of the d3d device */ /* Define a shared lock to synchronize the creation/destruction of the d3d device */
static GStaticMutex shared_d3d_lock = G_STATIC_MUTEX_INIT; static GStaticMutex shared_d3d_lock = G_STATIC_MUTEX_INIT;
static G_GNUC_UNUSED GStaticMutex shared_d3d_dev_lock = G_STATIC_MUTEX_INIT;
static GStaticMutex shared_d3d_hook_lock = G_STATIC_MUTEX_INIT; static GStaticMutex shared_d3d_hook_lock = G_STATIC_MUTEX_INIT;
/* Hold a reference to our dll's HINSTANCE */ /* Hold a reference to our dll's HINSTANCE */
static HINSTANCE g_hinstDll = NULL; static HINSTANCE g_hinstDll = NULL;
@ -155,12 +154,11 @@ static void gst_d3dvideosink_remove_window_for_renderer (GstD3DVideoSink *
sink); sink);
static gboolean gst_d3dvideosink_initialize_direct3d (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_initialize_direct3d (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_initialize_d3d_device (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_initialize_d3d_device (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_resize_swap_chain (GstD3DVideoSink * sink,
gint width, gint height) G_GNUC_UNUSED;
static gboolean gst_d3dvideosink_notify_device_init (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_notify_device_init (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_notify_device_lost (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_notify_device_lost (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_notify_device_reset (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_notify_device_reset (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_notify_device_resize (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_notify_device_reinit (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_device_lost (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_device_lost (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_release_d3d_device (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_release_d3d_device (GstD3DVideoSink * sink);
static gboolean gst_d3dvideosink_release_direct3d (GstD3DVideoSink * sink); static gboolean gst_d3dvideosink_release_direct3d (GstD3DVideoSink * sink);
@ -270,8 +268,7 @@ gst_d3dvideosink_base_init (gpointer klass)
{ {
GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_static_pad_template (element_class, gst_element_class_add_static_pad_template (element_class, &sink_template);
&sink_template);
gst_element_class_set_details_simple (element_class, "Direct3D video sink", gst_element_class_set_details_simple (element_class, "Direct3D video sink",
"Sink/Video", "Sink/Video",
@ -531,10 +528,7 @@ gst_d3dvideosink_create_shared_hidden_window (GstD3DVideoSink * sink)
goto failed; goto failed;
CloseHandle (shared.hidden_window_created_signal); CloseHandle (shared.hidden_window_created_signal);
/*
if (!shared.d3ddev)
goto failed;
*/
GST_DEBUG ("Successfully created Direct3D hidden window, handle: %p", GST_DEBUG ("Successfully created Direct3D hidden window, handle: %p",
shared.hidden_window_handle); shared.hidden_window_handle);
@ -639,7 +633,9 @@ SharedHiddenWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
shared.device_lost_sink = NULL; shared.device_lost_sink = NULL;
GST_DEBUG ("Initializing Direct3D"); GST_DEBUG ("Initializing Direct3D");
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
gst_d3dvideosink_initialize_d3d_device (sink); gst_d3dvideosink_initialize_d3d_device (sink);
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
GST_DEBUG ("Direct3D initialization complete"); GST_DEBUG ("Direct3D initialization complete");
break; break;
@ -664,9 +660,11 @@ SharedHiddenWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
/* Did we receive a message to check if the device is available again? */ /* Did we receive a message to check if the device is available again? */
if (wParam == IDT_DEVICELOST) { if (wParam == IDT_DEVICELOST) {
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
/* This will synchronously call SharedHiddenWndProc() because this thread is the one that created the window. */ /* This will synchronously call SharedHiddenWndProc() because this thread is the one that created the window. */
SendMessage (hWnd, WM_DIRECTX_D3D_DEVICELOST, 0, SendMessage (hWnd, WM_DIRECTX_D3D_DEVICELOST, 0,
(LPARAM) shared.device_lost_sink); (LPARAM) shared.device_lost_sink);
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return 0; return 0;
} }
break; break;
@ -736,6 +734,9 @@ WndProcHook (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
GstD3DVideoSink *sink = GstD3DVideoSink *sink =
(GstD3DVideoSink *) GetProp (hWnd, TEXT ("GstD3DVideoSink")); (GstD3DVideoSink *) GetProp (hWnd, TEXT ("GstD3DVideoSink"));
if (!sink)
return FALSE;
switch (message) { switch (message) {
case WM_ERASEBKGND: case WM_ERASEBKGND:
return TRUE; return TRUE;
@ -802,6 +803,8 @@ static void
gst_d3dvideosink_wnd_proc (GstD3DVideoSink * sink, HWND hWnd, UINT message, gst_d3dvideosink_wnd_proc (GstD3DVideoSink * sink, HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
if (!sink)
return;
switch (message) { switch (message) {
case WM_COPYDATA: case WM_COPYDATA:
{ {
@ -1069,12 +1072,18 @@ gst_d3dvideosink_set_window_handle (GstXOverlay * overlay, guintptr window_id)
/* If we're already playing/paused, then we need to lock the swap chain, and recreate it with the new window. */ /* If we're already playing/paused, then we need to lock the swap chain, and recreate it with the new window. */
if (sink->d3ddev != NULL) { if (sink->d3ddev != NULL) {
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
/* Close our existing window if there is one */ /* Close our existing window if there is one */
gst_d3dvideosink_close_window (sink); gst_d3dvideosink_close_window (sink);
/* Save our window id */ /* Save our window id */
sink->window_handle = hWnd; sink->window_handle = hWnd;
gst_d3dvideosink_set_window_for_renderer (sink); gst_d3dvideosink_set_window_for_renderer (sink);
gst_d3dvideosink_notify_device_resize (sink); sink->window_closed = FALSE;
gst_d3dvideosink_notify_device_reinit (sink);
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
//gst_d3dvideosink_notify_device_init(sink);
} else { } else {
sink->window_handle = hWnd; sink->window_handle = hWnd;
} }
@ -1314,8 +1323,6 @@ GST_D3DVIDEOSINK_SHARED_D3D_HOOK_UNLOCK GST_D3DVIDEOSINK_SHARED_D3D_UNLOCK}
static void static void
gst_d3dvideosink_remove_window_for_renderer (GstD3DVideoSink * sink) gst_d3dvideosink_remove_window_for_renderer (GstD3DVideoSink * sink)
{ {
//GST_D3DVIDEOSINK_SHARED_D3D_LOCK
//GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK(sink);
{ {
GST_DEBUG ("Removing custom rendering window procedure"); GST_DEBUG ("Removing custom rendering window procedure");
if (!sink->is_new_window && sink->window_handle) { if (!sink->is_new_window && sink->window_handle) {
@ -1342,8 +1349,6 @@ gst_d3dvideosink_remove_window_for_renderer (GstD3DVideoSink * sink)
/* Remove the property associating our sink with the window */ /* Remove the property associating our sink with the window */
RemoveProp (sink->window_handle, TEXT ("GstD3DVideoSink")); RemoveProp (sink->window_handle, TEXT ("GstD3DVideoSink"));
} }
//GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK(sink);
//GST_D3DVIDEOSINK_SHARED_D3D_UNLOCK
} }
static void static void
@ -1373,7 +1378,7 @@ gst_d3dvideosink_change_state (GstElement * element, GstStateChange transition)
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY: case GST_STATE_CHANGE_NULL_TO_READY:
if (!gst_d3dvideosink_initialize_direct3d (sink)) if (!gst_d3dvideosink_initialize_direct3d (sink))
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
break; break;
@ -2034,9 +2039,6 @@ gst_d3dvideosink_initialize_d3d_device (GstD3DVideoSink * sink)
/* Get the current size of the window */ /* Get the current size of the window */
gst_d3dvideosink_window_size (sink, &width, &height); gst_d3dvideosink_window_size (sink, &width, &height);
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
if (!shared.d3d) { if (!shared.d3d) {
GST_WARNING ("Direct3D object has not been initialized"); GST_WARNING ("Direct3D object has not been initialized");
goto error; goto error;
@ -2195,41 +2197,10 @@ gst_d3dvideosink_initialize_d3d_device (GstD3DVideoSink * sink)
//} //}
/*success:*/ /*success:*/
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink); //GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return TRUE; return TRUE;
error: error:
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink); //GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return FALSE;
}
static gboolean
gst_d3dvideosink_resize_swap_chain (GstD3DVideoSink * sink, gint width,
gint height)
{
if (width <= 0 || height <= 0 || width > GetSystemMetrics (SM_CXFULLSCREEN)
|| height > GetSystemMetrics (SM_CYFULLSCREEN)) {
GST_DEBUG ("Invalid size");
return FALSE;
}
if (!shared.d3d || !sink->d3ddev) {
GST_DEBUG_OBJECT (sink, "Direct3D device not initialized.");
return TRUE;
}
GST_LOG_OBJECT (sink, "Resizing Direct3D swap chain for sink %p to %dx%d",
sink, width, height);
/* actually recreates the device + associated surfaces
must be called from thread that created the device */
if (!gst_d3dvideosink_notify_device_resize (sink))
goto error;
/* success:*/
GST_LOG_OBJECT (sink, "Direct3D swap chain successfully resized");
return TRUE;
error:
GST_ERROR_OBJECT (sink, "Error attempting to resize the Direct3D swap chain");
return FALSE; return FALSE;
} }
@ -2244,10 +2215,10 @@ gst_d3dvideosink_notify_device_init (GstD3DVideoSink * sink)
} }
static gboolean static gboolean
gst_d3dvideosink_notify_device_resize (GstD3DVideoSink * sink) gst_d3dvideosink_notify_device_reinit (GstD3DVideoSink * sink)
{ {
if (sink->window_handle) { if (sink->window_handle) {
SendMessage (shared.hidden_window_handle, WM_DIRECTX_D3D_RESIZE, 0, SendMessage (shared.hidden_window_handle, WM_DIRECTX_D3D_DEVICELOST, 0,
(LPARAM) sink); (LPARAM) sink);
} }
return TRUE; return TRUE;
@ -2295,7 +2266,6 @@ gst_d3dvideosink_device_lost (GstD3DVideoSink * sink)
{ {
/* Must be called from hidden window's message loop! */ /* Must be called from hidden window's message loop! */
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
{ {
if (shared.device_lost) if (shared.device_lost)
GST_DEBUG ("Direct3D device lost"); GST_DEBUG ("Direct3D device lost");
@ -2343,18 +2313,15 @@ gst_d3dvideosink_device_lost (GstD3DVideoSink * sink)
/*success:*/ /*success:*/
GST_DEBUG ("Direct3D device has successfully been reset."); GST_DEBUG ("Direct3D device has successfully been reset.");
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return TRUE; return TRUE;
error: error:
GST_DEBUG ("Unable to successfully reset the Direct3D device."); GST_DEBUG ("Unable to successfully reset the Direct3D device.");
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return FALSE; return FALSE;
} }
static gboolean static gboolean
gst_d3dvideosink_release_d3d_device (GstD3DVideoSink * sink) gst_d3dvideosink_release_d3d_device (GstD3DVideoSink * sink)
{ {
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
if (sink->d3ddev) { if (sink->d3ddev) {
int ref_count; int ref_count;
ref_count = IDirect3DDevice9_Release (sink->d3ddev); ref_count = IDirect3DDevice9_Release (sink->d3ddev);
@ -2369,7 +2336,7 @@ gst_d3dvideosink_release_d3d_device (GstD3DVideoSink * sink)
GST_DEBUG_OBJECT (sink, GST_DEBUG_OBJECT (sink,
"Direct3D offscreen surface released. Reference count: %d", ref_count); "Direct3D offscreen surface released. Reference count: %d", ref_count);
} }
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink); //GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
return TRUE; return TRUE;
} }
@ -2391,7 +2358,9 @@ gst_d3dvideosink_release_direct3d (GstD3DVideoSink * sink)
if (shared.element_count > 0) if (shared.element_count > 0)
goto success; goto success;
GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
gst_d3dvideosink_release_d3d_device (sink); gst_d3dvideosink_release_d3d_device (sink);
GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
if (shared.d3d) { if (shared.d3d) {
int ref_count; int ref_count;
ref_count = IDirect3D9_Release (shared.d3d); ref_count = IDirect3D9_Release (shared.d3d);