static gboolean gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstStreamSplitter *stream_splitter = (GstStreamSplitter *) parent; gboolean res = TRUE; gboolean toall = FALSE; gboolean store = FALSE; gboolean eos = FALSE; gboolean flushpending = FALSE; /* FLUSH_START/STOP : forward to all * EOS : transform to CUSTOM_REAL_EOS and forward to all * INBAND events : store to send in chain function to selected chain * OUT_OF_BAND events : send to all */ GST_DEBUG_OBJECT (stream_splitter, "Got event %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); res = gst_stream_splitter_sink_setcaps (pad, caps); store = TRUE; break; } case GST_EVENT_FLUSH_STOP: flushpending = TRUE; toall = TRUE; break; case GST_EVENT_FLUSH_START: toall = TRUE; break; case GST_EVENT_EOS: /* Replace with our custom eos event */ gst_event_unref (event); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty ("stream-switching-eos")); toall = TRUE; eos = TRUE; break; default: if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED) store = TRUE; } if (flushpending) { g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref, NULL); g_list_free (stream_splitter->pending_events); stream_splitter->pending_events = NULL; } if (store) { stream_splitter->pending_events = g_list_append (stream_splitter->pending_events, event); } else if (toall || eos) { GList *tmp; guint32 cookie; /* Send to all pads */ STREAMS_LOCK (stream_splitter); resync: if (G_UNLIKELY (stream_splitter->srcpads == NULL)) { STREAMS_UNLOCK (stream_splitter); /* No source pads */ gst_event_unref (event); res = FALSE; goto beach; } tmp = stream_splitter->srcpads; cookie = stream_splitter->cookie; while (tmp) { GstPad *srcpad = (GstPad *) tmp->data; STREAMS_UNLOCK (stream_splitter); /* In case of EOS, we first push out the real one to flush out * each streams (but which will be discarded in the streamcombiner) * before our custom one (which will be converted back to and EOS * in the streamcombiner) */ if (eos) gst_pad_push_event (srcpad, gst_event_new_eos ()); gst_event_ref (event); res = gst_pad_push_event (srcpad, event); STREAMS_LOCK (stream_splitter); if (G_UNLIKELY (cookie != stream_splitter->cookie)) goto resync; tmp = tmp->next; } STREAMS_UNLOCK (stream_splitter); gst_event_unref (event); } else { GstPad *pad; /* Only send to current pad */ STREAMS_LOCK (stream_splitter); pad = stream_splitter->current; STREAMS_UNLOCK (stream_splitter); if (pad) res = gst_pad_push_event (pad, event); else { gst_event_unref (event); res = FALSE; } } beach: return res; }
static gboolean gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstStreamSplitter *stream_splitter = (GstStreamSplitter *) parent; gboolean res = TRUE; gboolean toall = FALSE; gboolean store = FALSE; gboolean flushpending = FALSE; /* FLUSH_START/STOP : forward to all * INBAND events : store to send in chain function to selected chain * OUT_OF_BAND events : send to all */ GST_DEBUG_OBJECT (stream_splitter, "Got event %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); res = gst_stream_splitter_sink_setcaps (pad, caps); store = TRUE; break; } case GST_EVENT_FLUSH_STOP: flushpending = TRUE; toall = TRUE; break; case GST_EVENT_FLUSH_START: toall = TRUE; break; case GST_EVENT_EOS: toall = TRUE; break; default: if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED) store = TRUE; } if (flushpending) { g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref, NULL); g_list_free (stream_splitter->pending_events); stream_splitter->pending_events = NULL; } if (store) { stream_splitter->pending_events = g_list_append (stream_splitter->pending_events, event); } else if (toall) { GList *tmp; guint32 cookie; /* Send to all pads */ STREAMS_LOCK (stream_splitter); resync: if (G_UNLIKELY (stream_splitter->srcpads == NULL)) { STREAMS_UNLOCK (stream_splitter); /* No source pads */ gst_event_unref (event); res = FALSE; goto beach; } tmp = stream_splitter->srcpads; cookie = stream_splitter->cookie; while (tmp) { GstPad *srcpad = (GstPad *) tmp->data; STREAMS_UNLOCK (stream_splitter); gst_event_ref (event); res = gst_pad_push_event (srcpad, event); STREAMS_LOCK (stream_splitter); if (G_UNLIKELY (cookie != stream_splitter->cookie)) goto resync; tmp = tmp->next; } STREAMS_UNLOCK (stream_splitter); gst_event_unref (event); } else { GstPad *pad; /* Only send to current pad */ STREAMS_LOCK (stream_splitter); pad = stream_splitter->current; STREAMS_UNLOCK (stream_splitter); if (pad) res = gst_pad_push_event (pad, event); else { gst_event_unref (event); res = FALSE; } } beach: return res; }