summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-05-19 19:45:06 +0200
committerWim Taymans <wim@metal.(none)>2009-06-01 13:37:29 +0200
commit642bb32196dcfe4f6db2d63a41ae7b4fe897ba07 (patch)
tree81af0c97d7f0c9c6043ce4480f3e189e913e5bb5
parent1caab05238e09f1c9b032ef0f57973e24f240b3e (diff)
basesink: catch step cases in _wait_preroll()
When a subclass is blocking in _wait_preroll() in the _render method, make sure we can unlock the subclass and detect this return value from the render method.
-rw-r--r--libs/gst/base/gstbasesink.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 616ecb245b..f717209896 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -152,6 +152,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_base_sink_debug);
#define GST_BASE_SINK_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SINK, GstBaseSinkPrivate))
+#define GST_FLOW_STEP GST_FLOW_CUSTOM_ERROR
+
typedef struct
{
gboolean valid; /* if this info is valid */
@@ -239,6 +241,7 @@ struct _GstBaseSinkPrivate
guint32 seqnum;
gboolean call_preroll;
+ gboolean step_unlock;
/* we have a pending and a current step operation */
GstStepInfo current_step;
@@ -1276,6 +1279,7 @@ gst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad)
basesink->eos = FALSE;
basesink->priv->received_eos = FALSE;
basesink->have_preroll = FALSE;
+ basesink->priv->step_unlock = FALSE;
basesink->eos_queued = FALSE;
basesink->preroll_queued = 0;
basesink->buffers_queued = 0;
@@ -1731,6 +1735,7 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
cstop = stop;
/* do running and stream time in TIME format */
format = GST_FORMAT_TIME;
+ GST_LOG_OBJECT (basesink, "not time format, don't clip");
goto do_times;
}
@@ -1934,6 +1939,8 @@ gst_base_sink_wait_preroll (GstBaseSink * sink)
sink->have_preroll = FALSE;
if (G_UNLIKELY (sink->flushing))
goto stopping;
+ if (G_UNLIKELY (sink->priv->step_unlock))
+ goto step_unlocked;
GST_DEBUG_OBJECT (sink, "continue after preroll");
return GST_FLOW_OK;
@@ -1941,9 +1948,15 @@ gst_base_sink_wait_preroll (GstBaseSink * sink)
/* ERRORS */
stopping:
{
- GST_DEBUG_OBJECT (sink, "preroll interrupted");
+ GST_DEBUG_OBJECT (sink, "preroll interrupted because of flush");
return GST_FLOW_WRONG_STATE;
}
+step_unlocked:
+ {
+ sink->priv->step_unlock = FALSE;
+ GST_DEBUG_OBJECT (sink, "preroll interrupted because of step");
+ return GST_FLOW_STEP;
+ }
}
/**
@@ -1980,8 +1993,12 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
if (G_LIKELY (sink->need_preroll)) {
/* block until the state changes, or we get a flush, or something */
ret = gst_base_sink_wait_preroll (sink);
- if (ret != GST_FLOW_OK)
- goto preroll_failed;
+ if (ret != GST_FLOW_OK) {
+ if (ret == GST_FLOW_STEP)
+ ret = GST_FLOW_OK;
+ else
+ goto preroll_failed;
+ }
}
}
return GST_FLOW_OK;
@@ -2029,8 +2046,12 @@ gst_base_sink_wait_eos (GstBaseSink * sink, GstClockTime time,
/* first wait for the playing state before we can continue */
if (G_UNLIKELY (sink->need_preroll)) {
ret = gst_base_sink_wait_preroll (sink);
- if (ret != GST_FLOW_OK)
- goto flushing;
+ if (ret != GST_FLOW_OK) {
+ if (ret == GST_FLOW_STEP)
+ ret = GST_FLOW_OK;
+ else
+ goto flushing;
+ }
}
/* preroll done, we can sync since we are in PLAYING now. */
@@ -2530,6 +2551,7 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
priv = basesink->priv;
+again:
late = FALSE;
ret = GST_FLOW_OK;
@@ -2567,10 +2589,13 @@ gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
ret = bclass->render (basesink, buf);
- priv->rendered++;
-
if (do_qos)
gst_base_sink_do_render_stats (basesink, FALSE);
+
+ if (ret == GST_FLOW_STEP)
+ goto again;
+
+ priv->rendered++;
}
} else {
GstEvent *event = GST_EVENT_CAST (obj);
@@ -3420,7 +3445,11 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
bclass->unlock (sink);
GST_PAD_PREROLL_LOCK (sink->sinkpad);
- /* update the segment */
+ /* now that we have the PREROLL lock, clear our unlock request */
+ if (bclass->unlock_stop)
+ bclass->unlock_stop (sink);
+
+ /* update the stepinfo and make it valid */
pending->seqnum = seqnum;
pending->format = format;
pending->amount = amount;
@@ -3430,10 +3459,6 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
pending->intermediate = intermediate;
pending->valid = TRUE;
- /* now that we have the PREROLL lock, clear our unlock request */
- if (bclass->unlock_stop)
- bclass->unlock_stop (sink);
-
if (sink->priv->async_enabled) {
/* and we need to commit our state again on the next
* prerolled buffer */
@@ -3453,9 +3478,11 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
gst_clock_id_unschedule (sink->clock_id);
}
- GST_DEBUG_OBJECT (sink, "signal waiter");
- GST_PAD_PREROLL_SIGNAL (sink->sinkpad);
-
+ if (sink->have_preroll) {
+ GST_DEBUG_OBJECT (sink, "signal waiter");
+ priv->step_unlock = TRUE;
+ GST_PAD_PREROLL_SIGNAL (sink->sinkpad);
+ }
GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
}
@@ -4314,6 +4341,7 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
GST_FORMAT_UNDEFINED);
basesink->offset = 0;
basesink->have_preroll = FALSE;
+ priv->step_unlock = FALSE;
basesink->need_preroll = TRUE;
basesink->playing_async = TRUE;
priv->current_sstart = -1;