adder: more seeking fixes.

When a seek failed upstream, make sure the adder sinkpad is set unflushing again
so that streaming can continue.
We only have a pending segment when we flushed.
Set the flush_stop_pending flag inside the appropriate locks and before we
attempt to perform the upstream seek.
Add some more comments.
Use the right lock to protect the flags in flush_stop.

See #585708
This commit is contained in:
Wim Taymans 2009-06-17 11:22:51 +02:00
parent 62f43a1c52
commit 85dbf93515

View file

@ -577,6 +577,7 @@ forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
g_value_set_boolean (ret, FALSE); g_value_set_boolean (ret, FALSE);
GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.", GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.",
event, GST_EVENT_TYPE_NAME (event)); event, GST_EVENT_TYPE_NAME (event));
gst_pad_send_event (pad, gst_event_new_flush_stop ());
} else { } else {
GST_LOG_OBJECT (pad, "Sent event %p (%s).", GST_LOG_OBJECT (pad, "Sent event %p (%s).",
event, GST_EVENT_TYPE_NAME (event)); event, GST_EVENT_TYPE_NAME (event));
@ -649,13 +650,16 @@ gst_adder_src_event (GstPad * pad, GstEvent * event)
GstSeekFlags flags; GstSeekFlags flags;
GstSeekType curtype; GstSeekType curtype;
gint64 cur; gint64 cur;
gboolean flush;
/* parse the seek parameters */ /* parse the seek parameters */
gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype, gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype,
&cur, NULL, NULL); &cur, NULL, NULL);
flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH;
/* check if we are flushing */ /* check if we are flushing */
if (flags & GST_SEEK_FLAG_FLUSH) { if (flush) {
/* make sure we accept nothing anymore and return WRONG_STATE */ /* make sure we accept nothing anymore and return WRONG_STATE */
gst_collect_pads_set_flushing (adder->collect, TRUE); gst_collect_pads_set_flushing (adder->collect, TRUE);
@ -664,29 +668,35 @@ gst_adder_src_event (GstPad * pad, GstEvent * event)
gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ()); gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ());
} }
GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event); GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event);
/* now wait for the collected to be finished and mark a new /* now wait for the collected to be finished and mark a new
* segment */ * 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_OBJECT_LOCK (adder->collect); GST_OBJECT_LOCK (adder->collect);
if (curtype == GST_SEEK_TYPE_SET) if (curtype == GST_SEEK_TYPE_SET)
adder->segment_position = cur; adder->segment_position = cur;
else else
adder->segment_position = 0; adder->segment_position = 0;
adder->segment_pending = TRUE; /* we flushed out the downstream segment, make sure we push a new one */
if (flush)
adder->segment_pending = TRUE;
/* we might have a pending flush_stop event now. This event will either be
* sent by an upstream element when it completes the seek or we will push
* one in the collected callback ourself */
adder->flush_stop_pending = flush;
GST_OBJECT_UNLOCK (adder->collect); GST_OBJECT_UNLOCK (adder->collect);
GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT, GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT,
event); event);
result = forward_event (adder, event); result = forward_event (adder, event);
if (!result) { if (!result) {
/* seek failed. maybe source is a live source. send a flush_stop /* seek failed. maybe source is a live source. */
* FIXME: ideally we just forward flush event, but live sources don't GST_DEBUG_OBJECT (adder, "seeking failed");
* send anything and we need a flush events to unlock the collect
* function
*/
GST_DEBUG_OBJECT (adder, "seeking failed, mark pending flush_stop");
adder->flush_stop_pending =
((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
} }
/* FIXME: ideally we would like to send a flush-stop event from here but
* collectpads does not have a method that allows us to do that. Instead
* we forward all flush-stop events we receive on the sinkpads. We might
* be sending too many flush-stop events. */
break; break;
} }
case GST_EVENT_QOS: case GST_EVENT_QOS:
@ -722,14 +732,17 @@ gst_adder_sink_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
/* mark a pending new segment. This event is synchronized /* we received a flush-stop. The collect_event function will push the
* with the streaming thread so we can safely update the * event past our element. We simply forward all flush-stop events, even
* variable without races. It's somewhat weird because we * when no flush-stop was pendingk, this is required because collectpads
* assume the collectpads forwarded the FLUSH_STOP past us * does not provide an API to handle-but-not-forward the flush-stop.
* and downstream (using our source pad, the bastard!). * We unset the pending flush-stop flag so that we don't send anymore
* flush-stop from the collect function later.
*/ */
GST_OBJECT_LOCK (adder->collect);
adder->segment_pending = TRUE; adder->segment_pending = TRUE;
adder->flush_stop_pending = FALSE; adder->flush_stop_pending = FALSE;
GST_OBJECT_UNLOCK (adder->collect);
break; break;
default: default:
break; break;