static gboolean gst_valve_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstValve *valve; gboolean is_sticky = GST_EVENT_IS_STICKY (event); gboolean ret = TRUE; valve = GST_VALVE (parent); if (g_atomic_int_get (&valve->drop)) { valve->need_repush_sticky |= is_sticky; gst_event_unref (event); } else { if (valve->need_repush_sticky) gst_valve_repush_sticky (valve); ret = gst_pad_event_default (pad, parent, event); } /* Ignore errors if "drop" was changed while the thread was blocked * downwards. */ if (g_atomic_int_get (&valve->drop)) { valve->need_repush_sticky |= is_sticky; ret = TRUE; } return ret; }
static gboolean mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; gboolean hard; MpegTSBase *base = GST_MPEGTS_BASE (parent); GST_DEBUG_OBJECT (base, "Got event %s", gst_event_type_get_name (GST_EVENT_TYPE (event))); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: gst_event_copy_segment (event, &base->segment); GST_DEBUG_OBJECT (base, "Received segment %" GST_SEGMENT_FORMAT, &base->segment); /* Check if we need to switch PCR/PTS handling */ if (base->segment.format == GST_FORMAT_TIME) { base->packetizer->calculate_offset = FALSE; base->packetizer->calculate_skew = TRUE; } else { base->packetizer->calculate_offset = TRUE; base->packetizer->calculate_skew = FALSE; } res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); break; case GST_EVENT_STREAM_START: gst_event_unref (event); break; case GST_EVENT_EOS: res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); res = gst_mpegts_base_handle_eos (base); break; case GST_EVENT_CAPS: /* FIXME, do something */ gst_event_unref (event); break; case GST_EVENT_FLUSH_STOP: res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); hard = (base->mode != BASE_MODE_SEEKING); mpegts_packetizer_flush (base->packetizer, hard); mpegts_base_flush (base, hard); gst_segment_init (&base->segment, GST_FORMAT_UNDEFINED); base->seen_pat = FALSE; break; default: res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); } /* Always return TRUE for sticky events */ if (GST_EVENT_IS_STICKY (event)) res = TRUE; return res; }
static gboolean gst_funnel_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstFunnel *funnel = GST_FUNNEL (parent); GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); gboolean forward = TRUE; gboolean res = TRUE; gboolean unlock = FALSE; GST_DEBUG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event); if (GST_EVENT_IS_STICKY (event)) { unlock = TRUE; GST_PAD_STREAM_LOCK (funnel->srcpad); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { GST_OBJECT_LOCK (funnel); fpad->got_eos = TRUE; if (!gst_funnel_all_sinkpads_eos_unlocked (funnel, pad)) { forward = FALSE; } else { forward = TRUE; } GST_OBJECT_UNLOCK (funnel); } else if (pad != funnel->last_sinkpad) { forward = FALSE; } } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { unlock = TRUE; GST_PAD_STREAM_LOCK (funnel->srcpad); GST_OBJECT_LOCK (funnel); fpad->got_eos = FALSE; GST_OBJECT_UNLOCK (funnel); } else if (GST_EVENT_TYPE (event) == GST_EVENT_GAP) { /* If no data is coming and we receive GAP event, need to forward sticky events. */ unlock = TRUE; GST_PAD_STREAM_LOCK (funnel->srcpad); GST_OBJECT_LOCK (funnel); gst_object_replace ((GstObject **) & funnel->last_sinkpad, GST_OBJECT (pad)); GST_OBJECT_UNLOCK (funnel); gst_pad_sticky_events_foreach (pad, forward_events, funnel->srcpad); } if (forward) res = gst_pad_push_event (funnel->srcpad, event); else gst_event_unref (event); if (unlock) GST_PAD_STREAM_UNLOCK (funnel->srcpad); return res; }
/* Queue the segment event if there was no caps event */ static gboolean gst_capsfilter_sink_event (GstBaseTransform * trans, GstEvent * event) { GstCapsFilter *filter = GST_CAPSFILTER (trans); if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { GList *l; for (l = filter->pending_events; l;) { if (GST_EVENT_TYPE (l->data) == GST_EVENT_SEGMENT) { gst_event_unref (l->data); l = g_list_delete_link (l, l); } else { l = l->next; } } } if (!GST_EVENT_IS_STICKY (event) || GST_EVENT_TYPE (event) <= GST_EVENT_CAPS) goto done; /* If we get EOS before any buffers, just push all pending events */ if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { GList *l; for (l = g_list_last (filter->pending_events); l; l = l->prev) { GST_LOG_OBJECT (trans, "Forwarding %s event", GST_EVENT_TYPE_NAME (l->data)); GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, l->data); } g_list_free (filter->pending_events); filter->pending_events = NULL; } else if (!gst_pad_has_current_caps (trans->sinkpad)) { GST_LOG_OBJECT (trans, "Got %s event before caps, queueing", GST_EVENT_TYPE_NAME (event)); filter->pending_events = g_list_prepend (filter->pending_events, event); return TRUE; } done: GST_LOG_OBJECT (trans, "Forwarding %s event", GST_EVENT_TYPE_NAME (event)); return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); }
static GList * _flush_events (GstPad * pad, GList * events) { GList *tmp; for (tmp = events; tmp; tmp = tmp->next) { if (GST_EVENT_TYPE (tmp->data) == GST_EVENT_EOS || GST_EVENT_TYPE (tmp->data) == GST_EVENT_SEGMENT || !GST_EVENT_IS_STICKY (tmp->data) || pad == NULL) { gst_event_unref (tmp->data); } else { gst_pad_store_sticky_event (pad, GST_EVENT_CAST (tmp->data)); } } g_list_free (events); return NULL; }
static gboolean gst_deinterleave_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstDeinterleave *self = GST_DEINTERLEAVE (parent); gboolean ret; GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad)); /* Send FLUSH_STOP, FLUSH_START and EOS immediately, no matter if * we have src pads already or not. Queue all other events and * push them after we have src pads */ switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_START: case GST_EVENT_EOS: ret = gst_pad_event_default (pad, parent, event); break; case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); ret = gst_deinterleave_sink_setcaps (self, caps); gst_event_unref (event); break; } default: if (!self->srcpads && !GST_EVENT_IS_STICKY (event)) { /* Sticky events are copied when creating a new pad */ GST_OBJECT_LOCK (self); self->pending_events = g_list_append (self->pending_events, event); GST_OBJECT_UNLOCK (self); ret = TRUE; } else { ret = gst_pad_event_default (pad, parent, event); } break; } return ret; }
gboolean gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, GstEvent * event, gboolean (*handler) (GstPad *, GstObject *, GstEvent *), GstObject * parent, GstPad * pad) { gboolean can_be_queued; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_STOP: case GST_EVENT_EOS: can_be_queued = FALSE; break; case GST_EVENT_SEGMENT: gst_kate_util_decoder_base_segment_event (decoder, event); can_be_queued = TRUE; break; default: can_be_queued = TRUE; break; } if (GST_EVENT_IS_STICKY (event) && GST_EVENT_TYPE (event) < GST_EVENT_CAPS) can_be_queued = FALSE; if (decoder->delay_events && can_be_queued) { GstKateDecoderBaseQueuedEvent *item; GST_DEBUG_OBJECT (decoder, "We have to delay the event"); item = g_slice_new (GstKateDecoderBaseQueuedEvent); if (item) { item->event = event; item->parent = parent; item->pad = pad; item->handler = handler; g_queue_push_tail (decoder->event_queue, item); return TRUE; } else { return FALSE; } } else { return FALSE; } }
static gboolean gst_type_find_element_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = FALSE; GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent); GST_DEBUG_OBJECT (typefind, "got %s event in mode %d", GST_EVENT_TYPE_NAME (event), typefind->mode); switch (typefind->mode) { case MODE_TYPEFIND: switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; /* Parse and push out our caps and data */ gst_event_parse_caps (event, &caps); res = gst_type_find_element_setcaps (typefind, caps); gst_event_unref (event); break; } case GST_EVENT_GAP: { GST_FIXME_OBJECT (typefind, "GAP events during typefinding not handled properly"); /* FIXME: These would need to be inserted in the stream at * the right position between buffers, but we combine all * buffers with a GstAdapter. Drop the GAP event for now, * which will only cause an implicit GAP between buffers. */ gst_event_unref (event); res = TRUE; break; } case GST_EVENT_EOS: { GST_INFO_OBJECT (typefind, "Got EOS and no type found yet"); gst_type_find_element_chain_do_typefinding (typefind, FALSE, TRUE); res = gst_pad_push_event (typefind->src, event); break; } case GST_EVENT_FLUSH_STOP:{ GList *l; GST_OBJECT_LOCK (typefind); for (l = typefind->cached_events; l; l = l->next) { if (GST_EVENT_IS_STICKY (l->data) && GST_EVENT_TYPE (l->data) != GST_EVENT_SEGMENT && GST_EVENT_TYPE (l->data) != GST_EVENT_EOS) { gst_pad_store_sticky_event (typefind->src, l->data); } gst_event_unref (l->data); } g_list_free (typefind->cached_events); typefind->cached_events = NULL; gst_adapter_clear (typefind->adapter); GST_OBJECT_UNLOCK (typefind); /* fall through */ } case GST_EVENT_FLUSH_START: res = gst_pad_push_event (typefind->src, event); break; default: /* Forward events that would happen before the caps event * directly instead of storing them. There's no reason not * to send them directly and we should only store events * for later sending that would need to come after the caps * event */ if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) { res = gst_pad_push_event (typefind->src, event); } else { GST_DEBUG_OBJECT (typefind, "Saving %s event to send later", GST_EVENT_TYPE_NAME (event)); GST_OBJECT_LOCK (typefind); typefind->cached_events = g_list_append (typefind->cached_events, event); GST_OBJECT_UNLOCK (typefind); res = TRUE; } break; } break; case MODE_NORMAL: res = gst_pad_push_event (typefind->src, event); break; case MODE_ERROR: break; default: g_assert_not_reached (); } return res; }
static gboolean gst_streamid_demux_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; GstStreamidDemux *demux; const gchar *stream_id = NULL; GstPad *active_srcpad = NULL; demux = GST_STREAMID_DEMUX (parent); GST_DEBUG_OBJECT (demux, "event = %s, sticky = %d", GST_EVENT_TYPE_NAME (event), GST_EVENT_IS_STICKY (event)); if (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START) { gst_event_parse_stream_start (event, &stream_id); if (!stream_id) goto no_stream_id; GST_OBJECT_LOCK (demux); active_srcpad = gst_streamid_demux_get_srcpad_by_stream_id (demux, stream_id); if (!active_srcpad) { /* try to generate a srcpad */ if (gst_streamid_demux_srcpad_create (demux, pad, stream_id)) { GST_OBJECT_UNLOCK (demux); gst_pad_set_active (demux->active_srcpad, TRUE); /* Forward sticky events to the new srcpad */ gst_pad_sticky_events_foreach (demux->sinkpad, forward_sticky_events, demux->active_srcpad); gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->active_srcpad); } else { GST_OBJECT_UNLOCK (demux); goto fail_create_srcpad; } } else if (demux->active_srcpad != active_srcpad) { demux->active_srcpad = active_srcpad; GST_OBJECT_UNLOCK (demux); g_object_notify (G_OBJECT (demux), "active-pad"); } else GST_OBJECT_UNLOCK (demux); } if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP || GST_EVENT_TYPE (event) == GST_EVENT_EOS) { res = gst_pad_event_default (pad, parent, event); } else if (demux->active_srcpad) { GstPad *srcpad = NULL; GST_OBJECT_LOCK (demux); srcpad = gst_object_ref (demux->active_srcpad); GST_OBJECT_UNLOCK (demux); res = gst_pad_push_event (srcpad, event); gst_object_unref (srcpad); } else { gst_event_unref (event); } return res; /* ERRORS */ no_stream_id: { GST_ELEMENT_ERROR (demux, STREAM, DEMUX, ("Error occurred trying to get stream-id to create a srcpad"), ("no stream-id found at %s", GST_EVENT_TYPE_NAME (event))); gst_event_unref (event); return FALSE; } fail_create_srcpad: { GST_ELEMENT_ERROR (demux, STREAM, FAILED, ("Error occurred trying to create a srcpad"), ("Failed to create a srcpad via stream-id:%s", stream_id)); gst_event_unref (event); return FALSE; } }