summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZaheer Abbas Merali <zaheerabbas@merali.org>2007-06-22 15:30:00 +0000
committerZaheer Abbas Merali <zaheerabbas@merali.org>2007-06-22 15:30:00 +0000
commitd6627ae8e08ddf3a645d0c961970edcfc4a2a3cd (patch)
treebc432985eb40b92ede7f05dfc5f9c0c5a8e2fa14
parent8eb58da4b47dff93075738afccd452ecbdf9342f (diff)
downloadgst-plugins-bad-d6627ae8e08ddf3a645d0c961970edcfc4a2a3cd.tar.gz
gst-plugins-bad-d6627ae8e08ddf3a645d0c961970edcfc4a2a3cd.tar.bz2
gst-plugins-bad-d6627ae8e08ddf3a645d0c961970edcfc4a2a3cd.zip
examples/switch/switcher.c (my_bus_callback, switch_timer, last_message_received, main): gst/switch/gstswitch.c (gst_...
Original commit message from CVS: * examples/switch/switcher.c (my_bus_callback, switch_timer, last_message_received, main): * gst/switch/gstswitch.c (gst_switch_release_pad, gst_switch_request_new_pad, gst_switch_chain, gst_switch_event, gst_switch_set_property, gst_switch_get_property, gst_switch_get_linked_pad, gst_switch_getcaps, gst_switch_bufferalloc, gst_switch_dispose, gst_switch_init): * gst/switch/gstswitch.h (switch_mutex, GST_SWITCH_LOCK, GST_SWITCH_UNLOCK): Add an extra lock to protect against certain variables instead of using the object lock. Fix case where caps are different in the sink pads causes deadlock. Update example to use different caps on each sink pad.
-rw-r--r--ChangeLog16
-rw-r--r--examples/switch/switcher.c15
-rw-r--r--gst/switch/gstswitch.c80
-rw-r--r--gst/switch/gstswitch.h4
4 files changed, 78 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index a946d03c..f8f11120 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-06-22 Zaheer Abbas Merali <zaheerabbas at merali dot org>
+
+ * examples/switch/switcher.c (my_bus_callback, switch_timer,
+ last_message_received, main):
+ * gst/switch/gstswitch.c (gst_switch_release_pad,
+ gst_switch_request_new_pad, gst_switch_chain, gst_switch_event,
+ gst_switch_set_property, gst_switch_get_property,
+ gst_switch_get_linked_pad, gst_switch_getcaps,
+ gst_switch_bufferalloc, gst_switch_dispose, gst_switch_init):
+ * gst/switch/gstswitch.h (switch_mutex, GST_SWITCH_LOCK,
+ GST_SWITCH_UNLOCK):
+ Add an extra lock to protect against certain variables instead of
+ using the object lock. Fix case where caps are different in the
+ sink pads causes deadlock. Update example to use different caps
+ on each sink pad.
+
2007-06-22 Jan Schmidt <thaytan@noraisin.net>
* MAINTAINERS:
diff --git a/examples/switch/switcher.c b/examples/switch/switcher.c
index 29f1d1a4..2faa26c7 100644
--- a/examples/switch/switcher.c
+++ b/examples/switch/switcher.c
@@ -68,6 +68,7 @@ switch_timer (GstElement * video_switch)
gint nb_sources;
gchar *active_pad;
+ g_message ("switching");
g_object_get (G_OBJECT (video_switch), "num-sources", &nb_sources, NULL);
g_object_get (G_OBJECT (video_switch), "active-pad", &active_pad, NULL);
@@ -97,7 +98,7 @@ int
main (int argc, char *argv[])
{
GstElement *pipeline, *src1, *src2, *video_switch, *video_sink, *segment;
- GstElement *sink1_sync, *sink2_sync;
+ GstElement *sink1_sync, *sink2_sync, *capsfilter, *scaler;
GstBus *bus;
/* Initing GStreamer library */
@@ -110,11 +111,15 @@ main (int argc, char *argv[])
g_object_set (G_OBJECT (src1), "pattern", 0, NULL);
src2 = gst_element_factory_make ("videotestsrc", "src2");
g_object_set (G_OBJECT (src2), "pattern", 1, NULL);
+ capsfilter = gst_element_factory_make ("capsfilter", "caps0");
+ g_object_set (G_OBJECT (capsfilter), "caps",
+ gst_caps_from_string ("video/x-raw-rgb,width=640,height=480"), NULL);
video_switch = gst_element_factory_make ("switch", "video_switch");
segment = gst_element_factory_make ("identity", "identity-segment");
g_signal_connect (G_OBJECT (segment), "notify::last-message",
G_CALLBACK (last_message_received), segment);
g_object_set (G_OBJECT (segment), "single-segment", TRUE, NULL);
+ scaler = gst_element_factory_make ("videoscale", "videoscale0");
video_sink = gst_element_factory_make ("ximagesink", "video_sink");
//g_object_set (G_OBJECT (video_sink), "sync", FALSE, NULL);
sink1_sync = gst_element_factory_make ("identity", "sink0_sync");
@@ -122,13 +127,15 @@ main (int argc, char *argv[])
sink2_sync = gst_element_factory_make ("identity", "sink1_sync");
g_object_set (G_OBJECT (sink2_sync), "sync", TRUE, NULL);
gst_bin_add_many (GST_BIN (pipeline), src1, src2, segment, video_switch,
- video_sink, sink1_sync, sink2_sync, NULL);
+ video_sink, sink1_sync, sink2_sync, scaler, capsfilter, NULL);
gst_element_link (src1, sink1_sync);
gst_element_link (sink1_sync, video_switch);
- gst_element_link (src2, sink2_sync);
+ gst_element_link (src2, capsfilter);
+ gst_element_link (capsfilter, sink2_sync);
gst_element_link (sink2_sync, video_switch);
gst_element_link (video_switch, segment);
- gst_element_link (segment, video_sink);
+ gst_element_link (segment, scaler);
+ gst_element_link (scaler, video_sink);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, my_bus_callback, NULL);
diff --git a/gst/switch/gstswitch.c b/gst/switch/gstswitch.c
index 73639d32..a7a20f85 100644
--- a/gst/switch/gstswitch.c
+++ b/gst/switch/gstswitch.c
@@ -127,6 +127,7 @@ gst_switch_release_pad (GstElement * element, GstPad * pad)
gst_element_remove_pad (element, pad);
GST_OBJECT_LOCK (gstswitch);
gstswitch->nb_sinkpads--;
+ GST_SWITCH_LOCK (gstswitch);
if (gstswitch->active_sinkpad == pad) {
gst_object_unref (gstswitch->active_sinkpad);
gstswitch->active_sinkpad = NULL;
@@ -144,6 +145,7 @@ gst_switch_release_pad (GstElement * element, GstPad * pad)
gst_iterator_free (iter);
}
}
+ GST_SWITCH_UNLOCK (gstswitch);
GST_OBJECT_UNLOCK (gstswitch);
}
@@ -173,8 +175,10 @@ gst_switch_request_new_pad (GstElement * element,
if (name)
g_free (name);
+ GST_SWITCH_LOCK (gstswitch);
if (gstswitch->active_sinkpad == NULL)
gstswitch->active_sinkpad = gst_object_ref (sinkpad);
+ GST_SWITCH_UNLOCK (gstswitch);
GST_OBJECT_UNLOCK (gstswitch);
gst_pad_set_getcaps_function (sinkpad,
@@ -201,12 +205,13 @@ gst_switch_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn res;
GstPad *active_sinkpad;
- GST_OBJECT_LOCK (gstswitch);
+ GST_SWITCH_LOCK (gstswitch);
active_sinkpad = gstswitch->active_sinkpad;
- GST_OBJECT_UNLOCK (gstswitch);
/* Ignore buffers from pads except the selected one */
if (pad != active_sinkpad) {
+ GST_SWITCH_UNLOCK (gstswitch);
+
GST_DEBUG_OBJECT (gstswitch, "Ignoring buffer %p from pad %s:%s",
buf, GST_DEBUG_PAD_NAME (pad));
@@ -216,7 +221,6 @@ gst_switch_chain (GstPad * pad, GstBuffer * buf)
}
/* check if we need to send a new segment event */
- GST_OBJECT_LOCK (gstswitch);
if (gstswitch->need_to_send_newsegment && !gstswitch->queue_buffers) {
/* check to see if we need to send a new segment update for stop */
if (gstswitch->previous_sinkpad != NULL) {
@@ -237,9 +241,11 @@ gst_switch_chain (GstPad * pad, GstBuffer * buf)
GST_DEBUG_OBJECT (gstswitch,
"Sending new segment update with stop of %" G_GUINT64_FORMAT,
gstswitch->stop_value);
+ GST_SWITCH_UNLOCK (gstswitch);
gst_pad_push_event (gstswitch->srcpad,
gst_event_new_new_segment_full (TRUE, rate, applied_rate, format,
gstswitch->current_start, gstswitch->stop_value, position));
+ GST_SWITCH_LOCK (gstswitch);
}
}
gst_object_unref (GST_OBJECT (gstswitch->previous_sinkpad));
@@ -283,18 +289,22 @@ gst_switch_chain (GstPad * pad, GstBuffer * buf)
g_hash_table_lookup (gstswitch->stored_buffers, active_sinkpad);
while (buffers != NULL) {
gst_buffer_ref (GST_BUFFER (buffers->data));
+ GST_SWITCH_UNLOCK (gstswitch);
gst_pad_push (gstswitch->srcpad, GST_BUFFER (buffers->data));
+ GST_SWITCH_LOCK (gstswitch);
buffers = buffers->next;
}
g_hash_table_remove (gstswitch->stored_buffers, active_sinkpad);
}
gstswitch->last_ts = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
if (!gstswitch->queue_buffers) {
- GST_OBJECT_UNLOCK (gstswitch);
/* forward */
- GST_DEBUG_OBJECT (gstswitch, "Forwarding buffer %p from pad %s:%s",
- buf, GST_DEBUG_PAD_NAME (pad));
+ GST_DEBUG_OBJECT (gstswitch, "Forwarding buffer %p from pad %s:%s to %s:%s",
+ buf, GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (gstswitch->srcpad));
+ GST_SWITCH_UNLOCK (gstswitch);
res = gst_pad_push (gstswitch->srcpad, buf);
+ GST_SWITCH_LOCK (gstswitch);
+ GST_DEBUG_OBJECT (gstswitch, "Finished pushing buffer");
} else {
GList *buffers;
gboolean lookup_res = TRUE;
@@ -306,10 +316,9 @@ gst_switch_chain (GstPad * pad, GstBuffer * buf)
/* only need to insert it if it was NULL before because we appended */
if (!lookup_res)
g_hash_table_insert (gstswitch->stored_buffers, active_sinkpad, buffers);
- GST_OBJECT_UNLOCK (gstswitch);
res = GST_FLOW_OK;
}
-
+ GST_SWITCH_UNLOCK (gstswitch);
gst_object_unref (gstswitch);
return res;
@@ -323,7 +332,7 @@ gst_switch_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
- GST_OBJECT_LOCK (gstswitch);
+ GST_SWITCH_LOCK (gstswitch);
/* need to put in or replace what's in hash table */
g_hash_table_replace (gstswitch->newsegment_events, pad, event);
if (pad == gstswitch->active_sinkpad) {
@@ -331,7 +340,7 @@ gst_switch_event (GstPad * pad, GstEvent * event)
gstswitch->need_to_send_newsegment = TRUE;
}
}
- GST_OBJECT_UNLOCK (gstswitch);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
default:
ret = gst_pad_event_default (pad, event);
@@ -367,9 +376,9 @@ gst_switch_set_property (GObject * object, guint prop_id,
pad = gst_element_get_pad (GST_ELEMENT (object), pad_name);
}
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
if (pad == gstswitch->active_sinkpad) {
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
if (pad)
gst_object_unref (pad);
break;
@@ -386,22 +395,22 @@ gst_switch_set_property (GObject * object, guint prop_id,
GST_DEBUG_OBJECT (gstswitch, "New active pad is %" GST_PTR_FORMAT,
gstswitch->active_sinkpad);
gstswitch->need_to_send_newsegment = TRUE;
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_START_VALUE:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
gstswitch->start_value = g_value_get_uint64 (value);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_STOP_VALUE:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
gstswitch->stop_value = g_value_get_uint64 (value);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_QUEUE_BUFFERS:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
gstswitch->queue_buffers = g_value_get_boolean (value);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -421,14 +430,14 @@ gst_switch_get_property (GObject * object, guint prop_id,
switch (prop_id) {
case ARG_ACTIVE_SOURCE:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
if (gstswitch->active_sinkpad != NULL) {
g_value_take_string (value,
gst_pad_get_name (gstswitch->active_sinkpad));
} else {
g_value_set_string (value, "");
}
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_NB_SOURCES:
GST_OBJECT_LOCK (object);
@@ -436,24 +445,24 @@ gst_switch_get_property (GObject * object, guint prop_id,
GST_OBJECT_UNLOCK (object);
break;
case ARG_START_VALUE:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
g_value_set_uint64 (value, gstswitch->start_value);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_STOP_VALUE:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
g_value_set_uint64 (value, gstswitch->stop_value);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_LAST_TS:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
g_value_set_uint64 (value, gstswitch->last_ts);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
case ARG_QUEUE_BUFFERS:
- GST_OBJECT_LOCK (object);
+ GST_SWITCH_LOCK (gstswitch);
g_value_set_boolean (value, gstswitch->queue_buffers);
- GST_OBJECT_UNLOCK (object);
+ GST_SWITCH_UNLOCK (gstswitch);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -480,15 +489,18 @@ gst_switch_get_linked_pad (GstPad * pad, gboolean strict)
static GstCaps *
gst_switch_getcaps (GstPad * pad)
{
- GstPad *otherpad = gst_switch_get_linked_pad (pad, FALSE);
+ GstPad *otherpad;
GstObject *parent;
GstCaps *caps;
+
parent = gst_object_get_parent (GST_OBJECT (pad));
+ GST_SWITCH_LOCK (GST_SWITCH (parent));
+ otherpad = gst_switch_get_linked_pad (pad, FALSE);
+ GST_SWITCH_UNLOCK (GST_SWITCH (parent));
if (!otherpad) {
GST_DEBUG_OBJECT (parent,
"Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad));
-
gst_object_unref (parent);
return gst_caps_new_any ();
}
@@ -514,9 +526,7 @@ gst_switch_bufferalloc (GstPad * pad, guint64 offset,
GstFlowReturn result;
GstPad *active_sinkpad;
- GST_OBJECT_LOCK (gstswitch);
active_sinkpad = gstswitch->active_sinkpad;
- GST_OBJECT_UNLOCK (gstswitch);
/* Fallback allocation for buffers from pads except the selected one */
if (pad != active_sinkpad) {
@@ -573,6 +583,9 @@ gst_switch_dispose (GObject * object)
gstswitch = GST_SWITCH (object);
+ if (gstswitch->switch_mutex) {
+ g_mutex_free (gstswitch->switch_mutex);
+ }
if (gstswitch->active_sinkpad) {
gst_object_unref (gstswitch->active_sinkpad);
gstswitch->active_sinkpad = NULL;
@@ -626,6 +639,7 @@ gst_switch_init (GstSwitch * gstswitch)
gstswitch->start_value = GST_CLOCK_TIME_NONE;
gstswitch->current_start = 0;
gstswitch->last_ts = GST_CLOCK_TIME_NONE;
+ gstswitch->switch_mutex = g_mutex_new ();
}
static void
diff --git a/gst/switch/gstswitch.h b/gst/switch/gstswitch.h
index e7a0ed86..c9ca0ec0 100644
--- a/gst/switch/gstswitch.h
+++ b/gst/switch/gstswitch.h
@@ -66,8 +66,12 @@ struct _GstSwitch {
* new segment has been sent
*/
GHashTable *stored_buffers;
+ GMutex *switch_mutex;
};
+#define GST_SWITCH_LOCK(obj) g_mutex_lock(obj->switch_mutex)
+#define GST_SWITCH_UNLOCK(obj) g_mutex_unlock(obj->switch_mutex)
+
struct _GstSwitchClass {
GstElementClass parent_class;
};