d3dvideosink: rework locking for devices lost
authorAndoni Morales Alastruey <ylatuya@gmail.com>
Tue, 19 Jun 2012 18:03:02 +0000 (20:03 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 26 Jun 2012 07:39:36 +0000 (09:39 +0200)
sys/d3dvideosink/d3dvideosink.c
sys/d3dvideosink/d3dvideosink.h

index 4aa7611..a22a019 100644 (file)
@@ -319,7 +319,7 @@ gst_d3dvideosink_init (GstD3DVideoSink * sink)
 {
   gst_d3dvideosink_clear (sink);
 
-  sink->d3d_swap_chain_lock = g_mutex_new ();
+  sink->d3d_device_lock = g_mutex_new ();
 
   sink->par = g_new0 (GValue, 1);
   g_value_init (sink->par, GST_TYPE_FRACTION);
@@ -341,8 +341,8 @@ gst_d3dvideosink_finalize (GObject * gobject)
     sink->par = NULL;
   }
 
-  g_mutex_free (sink->d3d_swap_chain_lock);
-  sink->d3d_swap_chain_lock = NULL;
+  g_mutex_free (sink->d3d_device_lock);
+  sink->d3d_device_lock = NULL;
 
   G_OBJECT_CLASS (parent_class)->finalize (gobject);
 }
@@ -588,6 +588,7 @@ gst_d3dvideosink_shared_hidden_window_thread (GstD3DVideoSink * sink)
 
   shared.hidden_window_handle = hWnd;
   shared.device_lost_timer = 0;
+  shared.device_lost = FALSE;
 
   gst_d3dvideosink_shared_hidden_window_created (sink);
 
@@ -643,27 +644,29 @@ SharedHiddenWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     {
       shared.device_lost_sink = NULL;
       GST_DEBUG ("Initializing Direct3D");
-      GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
-      gst_d3dvideosink_initialize_d3d_device (sink);
-      GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
-      GST_DEBUG ("Direct3D initialization complete");
+      if (!gst_d3dvideosink_initialize_d3d_device (sink))
+        gst_d3dvideosink_notify_device_lost(sink);
+      else
+        GST_DEBUG ("Direct3D initialization complete");
       break;
 
     }
     case WM_DIRECTX_D3D_INIT_DEVICELOST:
     {
-      if (!shared.device_lost) {
+      if (shared.device_lost)
+        break;
 
-        shared.device_lost = TRUE;
-        shared.device_lost_sink = sink;
+      shared.device_lost = TRUE;
+      GST_D3DVIDEOSINK_D3D_DEVICE_LOCK (sink);
 
-        /* Handle device lost by creating a timer and posting WM_D3D_DEVICELOST twice a second */
-        /* Create a timer to periodically check the d3d device and attempt to recreate it */
-        shared.device_lost_timer = SetTimer (hWnd, IDT_DEVICELOST, 500, NULL);
 
-        /* Try it once immediately */
-        SendMessage (hWnd, WM_DIRECTX_D3D_DEVICELOST, 0, (LPARAM) sink);
-      }
+      /* Handle device lost by creating a timer and posting WM_D3D_DEVICELOST twice a second */
+      /* Create a timer to periodically check the d3d device and attempt to recreate it */
+      shared.device_lost_timer = SetTimer (hWnd, IDT_DEVICELOST, 500, NULL);
+      shared.device_lost_sink = sink;
+
+      /* Try it once immediately */
+      SendMessage (hWnd, WM_DIRECTX_D3D_DEVICELOST, 0, (LPARAM) sink);
       break;
     }
     case WM_TIMER:
@@ -683,21 +686,24 @@ SharedHiddenWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     }
     case WM_DIRECTX_D3D_END_DEVICELOST:
     {
-      if (shared.device_lost) {
-        /* gst_d3dvideosink_notify_device_reset() sends this message. */
-        if (shared.device_lost_timer != 0)
-          KillTimer (hWnd, shared.device_lost_timer);
+      if (!shared.device_lost)
+        break;
 
-        shared.device_lost_timer = 0;
-        shared.device_lost = FALSE;
+      /* gst_d3dvideosink_notify_device_reset() sends this message. */
+      if (shared.device_lost_timer != 0)
+        KillTimer (hWnd, shared.device_lost_timer);
 
-        /* Refresh the video with the last buffer */
-        gst_d3dvideosink_update_all (sink);
+      shared.device_lost_timer = 0;
+      shared.device_lost = FALSE;
 
-        /* Then redraw just in case we don't have a last buffer */
-        gst_d3dvideosink_refresh_all (sink);
+      GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
+
+      /* Refresh the video with the last buffer */
+      gst_d3dvideosink_update_all (sink);
+
+      /* Then redraw just in case we don't have a last buffer */
+      gst_d3dvideosink_refresh_all (sink);
 
-      }
       shared.device_lost_sink = NULL;
       break;
     }
@@ -1078,9 +1084,9 @@ gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay, guintptr window_i
     return;
   }
 
+  GST_D3DVIDEOSINK_D3D_DEVICE_LOCK (sink);
   /* 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) {
-    GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
     /* Close our existing window if there is one */
     gst_d3dvideosink_close_window (sink);
     /* Save our window id */
@@ -1089,14 +1095,12 @@ gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay, guintptr window_i
     sink->window_closed = FALSE;
 
     gst_d3dvideosink_notify_device_reinit (sink);
-    GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
-    //gst_d3dvideosink_notify_device_init(sink);
-
   } else {
     sink->window_handle = hWnd;
   }
 
-/*success:*/
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
+
   GST_DEBUG_OBJECT (sink, "Direct3D window id successfully changed to %p",
       hWnd);
 
@@ -1375,13 +1379,17 @@ gst_d3dvideosink_prepare_window (GstD3DVideoSink * sink)
    * and create (and use) our own window, if we didn't create
    * one before */
   if (sink->window_handle && sink->is_new_window) {
-    gst_d3dvideosink_release_d3d_device (sink);
+    GST_D3DVIDEOSINK_D3D_DEVICE_LOCK(sink);
+    gst_d3dvideosink_release_d3d_device(sink);
+    GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK(sink);
   } else if (sink->window_handle) {
       gst_d3dvideosink_set_window_for_renderer (sink);
   } else {
     gst_d3dvideosink_create_default_window (sink);
   }
+  GST_D3DVIDEOSINK_D3D_DEVICE_LOCK(sink);
   gst_d3dvideosink_notify_device_init (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK(sink);
 }
 
 static GstStateChangeReturn
@@ -1625,7 +1633,8 @@ gst_d3dvideosink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
   GstD3DVideoSink *sink = GST_D3DVIDEOSINK (vsink);
   LPDIRECT3DSURFACE9 drawSurface = NULL;
 
-  GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
+  if (!GST_D3DVIDEOSINK_D3D_DEVICE_TRYLOCK (sink))
+    return GST_FLOW_OK;
   if (!sink->d3ddev) {
     if (!shared.device_lost) {
       GST_ERROR_OBJECT (sink, "No Direct3D device has been created, stopping");
@@ -1747,7 +1756,7 @@ gst_d3dvideosink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
     IDirect3DDevice9_EndScene (sink->d3ddev);
   }
 success:
-  GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
   gst_d3dvideosink_refresh (sink);
   return GST_FLOW_OK;
 #if 0
@@ -1760,7 +1769,7 @@ wrong_state:
 /*  return GST_FLOW_UNEXPECTED;               */
 #endif
 error:
-  GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
   return GST_FLOW_ERROR;
 }
 
@@ -1768,7 +1777,8 @@ error:
 static gboolean
 gst_d3dvideosink_refresh (GstD3DVideoSink * sink)
 {
-  GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
+  if (!GST_D3DVIDEOSINK_D3D_DEVICE_TRYLOCK (sink))
+    return TRUE;
   {
     HRESULT hr;
     LPDIRECT3DSURFACE9 backBuffer;
@@ -1823,10 +1833,10 @@ gst_d3dvideosink_refresh (GstD3DVideoSink * sink)
   }
 
 /*success:*/
-  GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
   return TRUE;
 error:
-  GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
   return FALSE;
 }
 
@@ -2361,9 +2371,10 @@ gst_d3dvideosink_release_direct3d (GstD3DVideoSink * sink)
   if (shared.element_count > 0)
     goto success;
 
-  GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_LOCK (sink);
   gst_d3dvideosink_release_d3d_device (sink);
-  GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK (sink);
+  GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK (sink);
+
   if (shared.d3d) {
     int ref_count;
     ref_count = IDirect3D9_Release (shared.d3d);
index 67877fa..6d9b495 100644 (file)
@@ -63,8 +63,9 @@ G_BEGIN_DECLS
 typedef struct _GstD3DVideoSink GstD3DVideoSink;
 typedef struct _GstD3DVideoSinkClass GstD3DVideoSinkClass;
 
-#define GST_D3DVIDEOSINK_SWAP_CHAIN_LOCK(sink)   g_mutex_lock (GST_D3DVIDEOSINK (sink)->d3d_swap_chain_lock);
-#define GST_D3DVIDEOSINK_SWAP_CHAIN_UNLOCK(sink)  g_mutex_unlock (GST_D3DVIDEOSINK (sink)->d3d_swap_chain_lock);
+#define GST_D3DVIDEOSINK_D3D_DEVICE_LOCK(sink) g_mutex_lock (GST_D3DVIDEOSINK (sink)->d3d_device_lock)
+#define GST_D3DVIDEOSINK_D3D_DEVICE_TRYLOCK(sink) g_mutex_trylock (GST_D3DVIDEOSINK (sink)->d3d_device_lock)
+#define GST_D3DVIDEOSINK_D3D_DEVICE_UNLOCK(sink) g_mutex_unlock (GST_D3DVIDEOSINK (sink)->d3d_device_lock)
 
 struct _GstD3DVideoSink
 {
@@ -99,7 +100,7 @@ struct _GstD3DVideoSink
   WNDPROC prevWndProc;
   gboolean is_hooked;
 
-  GMutex *d3d_swap_chain_lock;
+  GMutex *d3d_device_lock;
   LPDIRECT3DSURFACE9 d3d_offscreen_surface;
   LPDIRECT3DDEVICE9 d3ddev;
   D3DPRESENT_PARAMETERS d3dpp;