sys/ximage/ximagesink.c: Protect interface methods from chain and negotiation and...
authorJulien Moutte <julien@moutte.net>
Sat, 12 Feb 2005 18:41:49 +0000 (18:41 +0000)
committerJulien Moutte <julien@moutte.net>
Sat, 12 Feb 2005 18:41:49 +0000 (18:41 +0000)
Original commit message from CVS:
2005-02-12  Julien MOUTTE  <julien@moutte.net>

* sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new),
(gst_ximagesink_sink_link), (gst_ximagesink_change_state),
(gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id),
(gst_ximagesink_expose), (gst_ximagesink_set_property),
(gst_ximagesink_finalize), (gst_ximagesink_init): Protect interface
methods from chain and negotiation and vice versa (Fixes #166142).
* sys/ximage/ximagesink.h: Add stream_lock.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link),
(gst_xvimagesink_chain), (gst_xvimagesink_buffer_free),
(gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id),
(gst_xvimagesink_expose): Check for xcontext before trying to link.

ChangeLog
sys/ximage/ximagesink.c
sys/ximage/ximagesink.h
sys/xvimage/xvimagesink.c

index bfdc034..8552e72 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2005-02-12  Julien MOUTTE  <julien@moutte.net>
+
+       * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new),
+       (gst_ximagesink_sink_link), (gst_ximagesink_change_state),
+       (gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id),
+       (gst_ximagesink_expose), (gst_ximagesink_set_property),
+       (gst_ximagesink_finalize), (gst_ximagesink_init): Protect interface
+        methods from chain and negotiation and vice versa (Fixes #166142).
+       * sys/ximage/ximagesink.h: Add stream_lock.
+       * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link),
+       (gst_xvimagesink_chain), (gst_xvimagesink_buffer_free),
+       (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id),
+       (gst_xvimagesink_expose): Check for xcontext before trying to link.
+
 2005-02-12  Tim-Philipp Müller  <tim at centricular dot net>
 
        * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_open):
index aeb9888..05d5213 100644 (file)
@@ -389,6 +389,7 @@ static GstXWindow *
 gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
 {
   GstXWindow *xwindow = NULL;
+  XGCValues values;
 
   g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
 
@@ -408,7 +409,8 @@ gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
       StructureNotifyMask | PointerMotionMask | KeyPressMask |
       KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
 
-  xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, 0, NULL);
+  xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win,
+      0, &values);
 
   XMapRaised (ximagesink->xcontext->disp, xwindow->win);
 
@@ -976,6 +978,8 @@ gst_ximagesink_sink_link (GstPad * pad, const GstCaps * caps)
   if (!ret)
     return GST_PAD_LINK_REFUSED;
 
+  g_mutex_lock (ximagesink->stream_lock);
+
   /* if the caps contain pixel-aspect-ratio, they have to match ours,
    * otherwise linking should fail */
   par = gst_structure_get_value (structure, "pixel-aspect-ratio");
@@ -1008,6 +1012,8 @@ gst_ximagesink_sink_link (GstPad * pad, const GstCaps * caps)
     ximagesink->ximage = NULL;
   }
 
+  g_mutex_unlock (ximagesink->stream_lock);
+
   gst_x_overlay_got_desired_size (GST_X_OVERLAY (ximagesink),
       GST_VIDEOSINK_WIDTH (ximagesink), GST_VIDEOSINK_HEIGHT (ximagesink));
 
@@ -1031,7 +1037,9 @@ gst_ximagesink_change_state (GstElement * element)
       /* call XSynchronize with the current value of synchronous */
       GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
           ximagesink->synchronous ? "TRUE" : "FALSE");
+      g_mutex_lock (ximagesink->x_lock);
       XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
+      g_mutex_unlock (ximagesink->x_lock);
       break;
     case GST_STATE_READY_TO_PAUSED:
       ximagesink->time = 0;
@@ -1041,14 +1049,20 @@ gst_ximagesink_change_state (GstElement * element)
     case GST_STATE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_PAUSED_TO_READY:
+      g_mutex_lock (ximagesink->stream_lock);
       if (ximagesink->xwindow)
         gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
       ximagesink->framerate = 0;
       ximagesink->sw_scaling_failed = FALSE;
       GST_VIDEOSINK_WIDTH (ximagesink) = 0;
       GST_VIDEOSINK_HEIGHT (ximagesink) = 0;
+      g_mutex_unlock (ximagesink->stream_lock);
       break;
     case GST_STATE_READY_TO_NULL:
+      /* We are cleaning our resources here, yes i know chain is not running
+         but the interface can be called to set a window from a different thread
+         and that would crash */
+      g_mutex_lock (ximagesink->stream_lock);
       if (ximagesink->ximage) {
         gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
         ximagesink->ximage = NULL;
@@ -1066,6 +1080,7 @@ gst_ximagesink_change_state (GstElement * element)
         gst_ximagesink_xcontext_clear (ximagesink);
         ximagesink->xcontext = NULL;
       }
+      g_mutex_unlock (ximagesink->stream_lock);
       break;
   }
 
@@ -1091,6 +1106,8 @@ gst_ximagesink_chain (GstPad * pad, GstData * data)
     return;
   }
 
+  g_mutex_lock (ximagesink->stream_lock);
+
   buf = GST_BUFFER (data);
   /* update time */
   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
@@ -1139,6 +1156,8 @@ gst_ximagesink_chain (GstPad * pad, GstData * data)
   gst_buffer_unref (buf);
 
   gst_ximagesink_handle_xevents (ximagesink, pad);
+
+  g_mutex_unlock (ximagesink->stream_lock);
 }
 
 /* Buffer management */
@@ -1302,6 +1321,11 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
     return;
   }
 
+  /* We acquire the stream lock while setting this window in the element.
+     We are basically cleaning tons of stuff replacing the old window, putting
+     images while we do that would surely crash */
+  g_mutex_lock (ximagesink->stream_lock);
+
   /* Clear image pool as the images are unusable anyway */
   gst_ximagesink_imagepool_clear (ximagesink);
 
@@ -1385,6 +1409,8 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
 
   if (xwindow)
     ximagesink->xwindow = xwindow;
+
+  g_mutex_unlock (ximagesink->stream_lock);
 }
 
 static void
@@ -1405,6 +1431,10 @@ gst_ximagesink_expose (GstXOverlay * overlay)
   if (!ximagesink->xwindow)
     return;
 
+  /* We don't want chain to iterate while we do that. We might act on random
+     cur_image and different geometry */
+  g_mutex_lock (ximagesink->stream_lock);
+
   gst_ximagesink_xwindow_update_geometry (ximagesink, ximagesink->xwindow);
 
   /* We don't act on internal window from outside that could cause some thread
@@ -1416,6 +1446,8 @@ gst_ximagesink_expose (GstXOverlay * overlay)
 
   if (ximagesink->cur_image)
     gst_ximagesink_ximage_put (ximagesink, ximagesink->cur_image);
+
+  g_mutex_unlock (ximagesink->stream_lock);
 }
 
 static void
@@ -1451,7 +1483,9 @@ gst_ximagesink_set_property (GObject * object, guint prop_id,
       if (ximagesink->xcontext) {
         GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
             ximagesink->synchronous ? "TRUE" : "FALSE");
+        g_mutex_lock (ximagesink->x_lock);
         XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
+        g_mutex_unlock (ximagesink->x_lock);
       }
       break;
     case ARG_PIXEL_ASPECT_RATIO:
@@ -1519,6 +1553,10 @@ gst_ximagesink_finalize (GObject * object)
     g_mutex_free (ximagesink->x_lock);
     ximagesink->x_lock = NULL;
   }
+  if (ximagesink->stream_lock) {
+    g_mutex_free (ximagesink->stream_lock);
+    ximagesink->stream_lock = NULL;
+  }
   if (ximagesink->pool_lock) {
     g_mutex_free (ximagesink->pool_lock);
     ximagesink->pool_lock = NULL;
@@ -1557,7 +1595,7 @@ gst_ximagesink_init (GstXImageSink * ximagesink)
   ximagesink->framerate = 0;
 
   ximagesink->x_lock = g_mutex_new ();
-
+  ximagesink->stream_lock = g_mutex_new ();
 
   ximagesink->image_pool = NULL;
   ximagesink->pool_lock = g_mutex_new ();
index 36c832a..dcbc82c 100644 (file)
@@ -119,6 +119,7 @@ struct _GstXImageSink {
 
   gdouble framerate;
   GMutex *x_lock;
+  GMutex *stream_lock;
 
   /* Unused */
   gint pixel_width, pixel_height;
index d71ee73..2154fb2 100644 (file)
@@ -1203,6 +1203,9 @@ gst_xvimagesink_sink_link (GstPad * pad, const GstCaps * caps)
 
   xvimagesink = GST_XVIMAGESINK (gst_pad_get_parent (pad));
 
+  if (!xvimagesink->xcontext)
+    return GST_PAD_LINK_DELAYED;
+
   GST_DEBUG_OBJECT (xvimagesink,
       "sinkconnect possible caps %" GST_PTR_FORMAT " with given caps %"
       GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps);