From dd7f2c7076cbbfba16c1b4b4253bc8e800762b31 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 29 Jul 2008 11:57:11 +0000 Subject: [PATCH] plugins/elements/gsttee.*: Relay tag events in tee. Fixes parts of #474016. Original commit message from CVS: * plugins/elements/gsttee.c: * plugins/elements/gsttee.h: Relay tag events in tee. Fixes parts of #474016. --- ChangeLog | 6 +++ plugins/elements/gsttee.c | 108 ++++++++++++++++++++++++++++++++++---- plugins/elements/gsttee.h | 3 ++ 3 files changed, 107 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2172145eb5..fb42ff9b5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-07-29 Stefan Kost + + * plugins/elements/gsttee.c: + * plugins/elements/gsttee.h: + Relay tag events in tee. Fixes parts of #474016. + 2008-07-28 Michael Smith * configure.ac: diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c index 24cc4102e5..0901624290 100644 --- a/plugins/elements/gsttee.c +++ b/plugins/elements/gsttee.c @@ -99,6 +99,10 @@ typedef struct GstFlowReturn result; } PushData; +/* quark to keep track of which pads need events forwarded */ +static GQuark need_events; + + static GstPad *gst_tee_request_new_pad (GstElement * element, GstPadTemplate * temp, const gchar * unused); static void gst_tee_release_pad (GstElement * element, GstPad * pad); @@ -113,10 +117,13 @@ static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_tee_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active); +static gboolean gst_tee_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_tee_src_check_get_range (GstPad * pad); static gboolean gst_tee_src_activate_pull (GstPad * pad, gboolean active); static GstFlowReturn gst_tee_src_get_range (GstPad * pad, guint64 offset, guint length, GstBuffer ** buf); +static GstPadLinkReturn gst_tee_src_link (GstPad * pad, GstPad * peer); + static void @@ -135,17 +142,26 @@ gst_tee_base_init (gpointer g_class) gst_static_pad_template_get (&tee_src_template)); push_data = g_quark_from_static_string ("tee-push-data"); + need_events = g_quark_from_static_string ("tee-need-events"); +} + +static void +gst_tee_reset (GstTee * tee) +{ + g_free (tee->last_message); + tee->last_message = NULL; + + if (tee->tags) + gst_tag_list_free (tee->tags); + tee->tags = NULL; + + tee->have_events = FALSE; } static void gst_tee_finalize (GObject * object) { - GstTee *tee; - - tee = GST_TEE (object); - - g_free (tee->last_message); - + gst_tee_reset (GST_TEE (object)); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -208,10 +224,46 @@ gst_tee_init (GstTee * tee, GstTeeClass * g_class) GST_DEBUG_FUNCPTR (gst_tee_buffer_alloc)); gst_pad_set_activatepush_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push)); + gst_pad_set_event_function (tee->sinkpad, gst_tee_sink_event); gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain)); gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); - tee->last_message = NULL; + gst_tee_reset (tee); +} + +static gboolean +gst_tee_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstTee *tee; + + tee = GST_TEE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG:{ + GstTagList *list; + + GST_DEBUG_OBJECT (tee, "got a tag event"); + gst_event_parse_tag (event, &list); + if (tee->tags) { + gst_tag_list_insert (tee->tags, list, GST_TAG_MERGE_PREPEND); + } else { + tee->tags = gst_tag_list_copy (list); + } + tee->have_events = TRUE; + } + break; + case GST_EVENT_EOS: + /* re-gather events on next run */ + gst_tee_reset (tee); + break; + default: + break; + } + res = gst_pad_event_default (pad, event); + gst_object_unref (tee); + + return res; } static GstPad * @@ -271,6 +323,7 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_DEBUG_FUNCPTR (gst_tee_src_check_get_range)); gst_pad_set_getrange_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_get_range)); + gst_pad_set_link_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_link)); gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad); return srcpad; @@ -441,7 +494,7 @@ gst_tee_buffer_alloc (GstPad * pad, guint64 offset, guint size, if ((allocpad = tee->allocpad)) { /* if we had a previous pad we used for allocating a buffer, continue using * it. */ - GST_DEBUG_OBJECT (tee, "using pad %s:%s for alloc", + GST_LOG_OBJECT (tee, "using pad %s:%s for alloc", GST_DEBUG_PAD_NAME (allocpad)); gst_object_ref (allocpad); GST_OBJECT_UNLOCK (tee); @@ -484,6 +537,18 @@ gst_tee_do_push (GstTee * tee, GstPad * pad, GstBuffer * buffer) /* don't push on the pad we're pulling from */ res = GST_FLOW_OK; } else { + + if (G_UNLIKELY (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (pad), + need_events)))) { + g_object_set_qdata (G_OBJECT (pad), need_events, NULL); + + if (tee->tags) { + gst_pad_push_event (pad, + gst_event_new_tag (gst_tag_list_copy (tee->tags))); + } + GST_DEBUG_OBJECT (tee, "events sent on %s:%s", GST_DEBUG_PAD_NAME (pad)); + } + res = gst_pad_push (pad, gst_buffer_ref (buffer)); } return res; @@ -601,11 +666,11 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer) tee = GST_TEE (gst_pad_get_parent (pad)); - GST_DEBUG_OBJECT (tee, "received buffer %p", buffer); + GST_LOG_OBJECT (tee, "received buffer %p", buffer); res = gst_tee_handle_buffer (tee, buffer); - GST_DEBUG_OBJECT (tee, "handled buffer %s", gst_flow_get_name (res)); + GST_LOG_OBJECT (tee, "handled buffer %s", gst_flow_get_name (res)); gst_object_unref (tee); @@ -791,3 +856,26 @@ gst_tee_src_get_range (GstPad * pad, guint64 offset, guint length, return ret; } + +static GstPadLinkReturn +gst_tee_src_link (GstPad * pad, GstPad * peer) +{ + GstPadLinkReturn result = GST_PAD_LINK_OK; + GstTee *tee; + + tee = GST_TEE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (tee, "linking source pad"); + + if (GST_PAD_LINKFUNC (peer)) { + result = GST_PAD_LINKFUNC (peer) (peer, pad); + } + + if (GST_PAD_LINK_SUCCESSFUL (result) && tee->have_events) { + /* mark dynamically linked elements */ + g_object_set_qdata (G_OBJECT (pad), need_events, GINT_TO_POINTER (TRUE)); + } + gst_object_unref (tee); + + return result; +} diff --git a/plugins/elements/gsttee.h b/plugins/elements/gsttee.h index 67d4c61cd3..1baf8d61fc 100644 --- a/plugins/elements/gsttee.h +++ b/plugins/elements/gsttee.h @@ -78,6 +78,9 @@ struct _GstTee { GstActivateMode sink_mode; GstTeePullMode pull_mode; GstPad *pull_pad; + + GstTagList *tags; + gboolean have_events; }; struct _GstTeeClass {