Index: gst/videomixer/videomixer.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/gst/videomixer/videomixer.c,v
retrieving revision 1.33
diff -u -r1.33 videomixer.c
--- gst/videomixer/videomixer.c	6 Dec 2006 15:06:04 -0000	1.33
+++ gst/videomixer/videomixer.c	6 Dec 2006 16:19:01 -0000
@@ -82,6 +82,13 @@
 #define GST_IS_VIDEO_MIXER_CLASS(klass) \
         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MIXER))
 
+#define GST_VIDEO_MIXER_GET_STATE_LOCK(mix) \
+  (GST_VIDEO_MIXER(mix)->state_lock)
+#define GST_VIDEO_MIXER_STATE_LOCK(mix) \
+  (g_mutex_lock(GST_VIDEO_MIXER_GET_STATE_LOCK (mix)))
+#define GST_VIDEO_MIXER_STATE_UNLOCK(mix) \
+  (g_mutex_unlock(GST_VIDEO_MIXER_GET_STATE_LOCK (mix)))
+
 static GType gst_videomixer_get_type (void);
 
 typedef struct _GstVideoMixer GstVideoMixer;
@@ -284,6 +291,8 @@
   /* pad */
   GstPad *srcpad;
 
+  /* Lock to prevent the state to change while blending */
+  GMutex *state_lock;
   /* Sink pads using Collect Pads from core's base library */
   GstCollectPads *collect;
   /* sinkpads, a GSList of GstVideoMixerPads */
@@ -573,12 +582,8 @@
 }
 
 static void
-gst_videomixer_collect_free (GstCollectData * collect)
+gst_videomixer_collect_free (GstVideoMixerCollect * mixcol)
 {
-  GstVideoMixerCollect *mixcol;
-
-  mixcol = (GstVideoMixerCollect *) collect;
-
   if (mixcol->buffer) {
     gst_buffer_unref (mixcol->buffer);
     mixcol->buffer = NULL;
@@ -600,7 +605,7 @@
   /* clean up collect data */
   walk = mix->collect->data;
   while (walk) {
-    GstCollectData *data = (GstCollectData *) walk->data;
+    GstVideoMixerCollect *data = (GstVideoMixerCollect *) walk->data;
 
     gst_videomixer_collect_free (data);
     walk = g_slist_next (walk);
@@ -626,6 +631,7 @@
       (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_videomixer_collected),
       mix);
 
+  mix->state_lock = g_mutex_new();
   /* initialize variables */
   gst_videomixer_reset (mix);
 
@@ -637,6 +643,7 @@
   GstVideoMixer *mix = GST_VIDEO_MIXER (object);
 
   gst_object_unref (mix->collect);
+  g_mutex_free(mix->state_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -711,6 +718,7 @@
     mixpad->ypos = DEFAULT_PAD_YPOS;
     mixpad->alpha = DEFAULT_PAD_ALPHA;
 
+    GST_VIDEO_MIXER_STATE_LOCK(mix);
     mixcol = (GstVideoMixerCollect *)
         gst_collect_pads_add_pad (mix->collect, GST_PAD (mixpad),
         sizeof (GstVideoMixerCollect));
@@ -722,6 +730,7 @@
     /* Keep an internal list of mixpads for zordering */
     mix->sinkpads = g_slist_append (mix->sinkpads, mixpad);
     mix->numpads++;
+    GST_VIDEO_MIXER_STATE_UNLOCK(mix);
   } else {
     g_warning ("videomixer: this is not our template!\n");
     return NULL;
@@ -738,31 +747,28 @@
 gst_videomixer_release_pad (GstElement * element, GstPad * pad)
 {
   GstVideoMixer *mix = NULL;
-  GSList *walk = NULL;
+  GstVideoMixerPad *mixpad;
 
   mix = GST_VIDEO_MIXER (element);
-
-  walk = mix->collect->data;
-  while (walk) {
-    GstCollectData *data = (GstCollectData *) walk->data;
-    GstVideoMixerCollect *mixcol = (GstVideoMixerCollect *) data;
-    GstVideoMixerPad *mixpad = mixcol->mixpad;
-
-    walk = g_slist_next (walk);
-
-    if (mixpad == GST_VIDEO_MIXER_PAD (pad)) {
-      /* found it, remove from all sorts of lists */
-      mix->sinkpads = g_slist_remove (mix->sinkpads, pad);
-      gst_videomixer_collect_free (data);
-      gst_collect_pads_remove_pad (mix->collect, pad);
-      gst_element_remove_pad (element, pad);
-      /* determine possibly new geometry and master */
-      gst_videomixer_set_master_geometry (mix);
-      return;
-    }
+  GST_VIDEO_MIXER_STATE_LOCK(mix);
+  if (G_UNLIKELY(g_slist_find(mix->sinkpads, pad) == NULL)) {
+    g_warning ("Unknown pad %s", GST_PAD_NAME (pad));
+    goto error;
   }
 
-  g_warning ("Unknown pad %s", GST_PAD_NAME (pad));
+  mixpad = GST_VIDEO_MIXER_PAD(pad);
+
+  mix->sinkpads = g_slist_remove (mix->sinkpads, pad);
+  gst_videomixer_collect_free (mixpad->mixcol);
+  gst_collect_pads_remove_pad (mix->collect, pad);
+  /* determine possibly new geometry and master */
+  gst_videomixer_set_master_geometry (mix);
+  GST_VIDEO_MIXER_STATE_UNLOCK(mix);
+
+  gst_element_remove_pad (element, pad);
+  return;
+error:
+ GST_VIDEO_MIXER_STATE_UNLOCK(mix);
 }
 
 #define BLEND_NORMAL(Y1,U1,V1,Y2,U2,V2,alpha,Y,U,V)     \
@@ -1236,6 +1242,7 @@
   g_return_val_if_fail (GST_IS_VIDEO_MIXER (mix), GST_FLOW_ERROR);
 
   GST_LOG ("all pads are collected");
+  GST_VIDEO_MIXER_STATE_LOCK(mix);
 
   eos = gst_videomixer_fill_queues (mix);
 
@@ -1244,7 +1251,7 @@
     GST_LOG ("all our sinkpads are EOS, pushing downstream");
     gst_pad_push_event (mix->srcpad, gst_event_new_eos ());
     ret = GST_FLOW_WRONG_STATE;
-    goto beach;
+    goto error;
   }
 
   /* Calculating out buffer size from input size */
@@ -1277,7 +1284,7 @@
   }
 
   if (ret != GST_FLOW_OK) {
-    goto beach;
+    goto error;
   }
 
   switch (mix->background) {
@@ -1298,11 +1305,15 @@
   gst_videomixer_blend_buffers (mix, outbuf);
 
   gst_videomixer_update_queues (mix);
+  GST_VIDEO_MIXER_STATE_UNLOCK(mix);
 
   ret = gst_pad_push (mix->srcpad, outbuf);
 
 beach:
   return ret;
+error:
+  GST_VIDEO_MIXER_STATE_UNLOCK(mix);
+  goto beach;
 }
 
 static void
@@ -1349,13 +1360,13 @@
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      gst_videomixer_reset (mix);
       GST_LOG ("starting collectpads");
       gst_collect_pads_start (mix->collect);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_LOG ("stopping collectpads");
       gst_collect_pads_stop (mix->collect);
+      gst_videomixer_reset (mix);
       break;
     default:
       break;
