static gboolean gst_adder_sink_event (GstCollectPads2 * pads, GstCollectData2 * pad, GstEvent * event, gpointer user_data) { GstAdder *adder = GST_ADDER (user_data); gboolean res = FALSE; GST_DEBUG_OBJECT (pad->pad, "Got %s event on sink pad from %s", GST_EVENT_TYPE_NAME (event), GST_OBJECT_NAME (GST_EVENT_SRC (event))); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: /* drop flush start events, as we forwarded one already when handing the * flushing seek on the sink pad */ gst_event_unref (event); res = TRUE; break; case GST_EVENT_FLUSH_STOP: /* we received a flush-stop. We will only forward it when * flush_stop_pending is set, and we will unset it then. */ if (g_atomic_int_compare_and_exchange (&adder->flush_stop_pending, TRUE, FALSE)) { g_atomic_int_set (&adder->new_segment_pending, TRUE); GST_DEBUG_OBJECT (pad->pad, "forwarding flush stop"); } else { gst_event_unref (event); res = TRUE; GST_DEBUG_OBJECT (pad->pad, "eating flush stop"); } /* Clear pending tags */ if (adder->pending_events) { g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL); g_list_free (adder->pending_events); adder->pending_events = NULL; } break; case GST_EVENT_TAG: /* collect tags here so we can push them out when we collect data */ adder->pending_events = g_list_append (adder->pending_events, event); res = TRUE; break; case GST_EVENT_NEWSEGMENT: if (g_atomic_int_compare_and_exchange (&adder->wait_for_new_segment, TRUE, FALSE)) { /* make sure we push a new segment, to inform about new basetime * see FIXME in gst_adder_collected() */ g_atomic_int_set (&adder->new_segment_pending, TRUE); } gst_event_unref (event); res = TRUE; break; default: break; } return res; }
static void gst_event_finalize (GstEvent * event) { g_return_if_fail (event != NULL); g_return_if_fail (GST_IS_EVENT (event)); GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event, GST_EVENT_TYPE_NAME (event)); if (GST_EVENT_SRC (event)) { gst_object_unref (GST_EVENT_SRC (event)); GST_EVENT_SRC (event) = NULL; } if (event->structure) { gst_structure_set_parent_refcount (event->structure, NULL); gst_structure_free (event->structure); } /* GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event)); */ }
static GstEvent * _gst_event_copy (GstEvent * event) { GstEvent *copy; copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT); GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event); GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event); GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event); if (GST_EVENT_SRC (event)) { GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event)); } if (event->structure) { copy->structure = gst_structure_copy (event->structure); gst_structure_set_parent_refcount (copy->structure, ©->mini_object.refcount); } return copy; }
static gboolean gst_adder_src_event (GstPad * pad, GstEvent * event) { GstAdder *adder; gboolean result; adder = GST_ADDER (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (pad, "Got %s event on src pad from %s", GST_EVENT_TYPE_NAME (event), GST_OBJECT_NAME (GST_EVENT_SRC (event))); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: { GstSeekFlags flags; GstSeekType curtype, endtype; gint64 cur, end; gboolean flush; /* parse the seek parameters */ gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype, &cur, &endtype, &end); if ((curtype != GST_SEEK_TYPE_NONE) && (curtype != GST_SEEK_TYPE_SET)) { result = FALSE; GST_DEBUG_OBJECT (adder, "seeking failed, unhandled seek type for start: %d", curtype); goto done; } if ((endtype != GST_SEEK_TYPE_NONE) && (endtype != GST_SEEK_TYPE_SET)) { result = FALSE; GST_DEBUG_OBJECT (adder, "seeking failed, unhandled seek type for end: %d", endtype); goto done; } flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH; /* check if we are flushing */ if (flush) { /* flushing seek, start flush downstream, the flush will be done * when all pads received a FLUSH_STOP. * Make sure we accept nothing anymore and return WRONG_STATE. * We send a flush-start before, to ensure no streaming is done * as we need to take the stream lock. */ gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ()); gst_collect_pads2_set_flushing (adder->collect, TRUE); /* We can't send FLUSH_STOP here since upstream could start pushing data * after we unlock adder->collect. * We set flush_stop_pending to TRUE instead and send FLUSH_STOP after * forwarding the seek upstream or from gst_adder_collected, * whichever happens first. */ g_atomic_int_set (&adder->flush_stop_pending, TRUE); } GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event); /* now wait for the collected to be finished and mark a new * segment. After we have the lock, no collect function is running and no * new collect function will be called for as long as we're flushing. */ GST_COLLECT_PADS2_STREAM_LOCK (adder->collect); if (curtype == GST_SEEK_TYPE_SET) adder->segment_start = cur; else adder->segment_start = 0; if (endtype == GST_SEEK_TYPE_SET) adder->segment_end = end; else adder->segment_end = GST_CLOCK_TIME_NONE; if (flush) { /* Yes, we need to call _set_flushing again *WHEN* the streaming threads * have stopped so that the cookie gets properly updated. */ gst_collect_pads2_set_flushing (adder->collect, TRUE); } GST_COLLECT_PADS2_STREAM_UNLOCK (adder->collect); GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT, event); /* we're forwarding seek to all upstream peers and wait for one to reply * with a newsegment-event before we send a newsegment-event downstream */ g_atomic_int_set (&adder->wait_for_new_segment, TRUE); result = forward_event (adder, event, flush); if (!result) { /* seek failed. maybe source is a live source. */ GST_DEBUG_OBJECT (adder, "seeking failed"); } if (g_atomic_int_compare_and_exchange (&adder->flush_stop_pending, TRUE, FALSE)) { GST_DEBUG_OBJECT (adder, "pending flush stop"); gst_pad_push_event (adder->srcpad, gst_event_new_flush_stop ()); } break; } case GST_EVENT_QOS: /* QoS might be tricky */ result = FALSE; break; case GST_EVENT_NAVIGATION: /* navigation is rather pointless. */ result = FALSE; break; default: /* just forward the rest for now */ GST_DEBUG_OBJECT (adder, "forward unhandled event: %s", GST_EVENT_TYPE_NAME (event)); result = forward_event (adder, event, FALSE); break; } done: gst_object_unref (adder); return result; }