mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
Make sure that when a pipeline goes to PLAYING, that data has actually hit the sink.
Original commit message from CVS: 2005-08-18 Andy Wingo <wingo@pobox.com> Make sure that when a pipeline goes to PLAYING, that data has actually hit the sink. * check/states/sinks.c (test_sink): A sink that doesn't get any data shouldn't return SUCCESS for going to either PLAYING or PAUSED. Test also the return values on the way back down. * gst/gstelement.c (gst_element_set_state): When changing the state of an element currently changing state asynchronously, go to lost-state after commiting the pending state. Makes future calls to get_state continue to return ASYNC. * gst/base/gstbasesink.c (gst_base_sink_change_state): Return ASYNC when going to PLAYING if we still don't have preroll, as can happen with live sources.
This commit is contained in:
parent
16e1f6e89d
commit
aa0fb69d49
8 changed files with 141 additions and 18 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2005-08-18 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
Make sure that when a pipeline goes to PLAYING, that data has
|
||||
actually hit the sink.
|
||||
|
||||
* check/states/sinks.c (test_sink): A sink that doesn't get any
|
||||
data shouldn't return SUCCESS for going to either PLAYING or
|
||||
PAUSED. Test also the return values on the way back down.
|
||||
|
||||
* gst/gstelement.c (gst_element_set_state): When changing the
|
||||
state of an element currently changing state asynchronously, go to
|
||||
lost-state after commiting the pending state. Makes future calls
|
||||
to get_state continue to return ASYNC.
|
||||
|
||||
* gst/base/gstbasesink.c (gst_base_sink_change_state): Return
|
||||
ASYNC when going to PLAYING if we still don't have preroll, as can
|
||||
happen with live sources.
|
||||
|
||||
2005-08-18 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
|
||||
* docs/pwg/advanced-types.xml:
|
||||
|
|
|
@ -28,6 +28,7 @@ GST_START_TEST (test_sink)
|
|||
GstElement *sink;
|
||||
GstElementStateReturn ret;
|
||||
GstElementState current, pending;
|
||||
GTimeVal tv;
|
||||
|
||||
sink = gst_element_factory_make ("fakesink", "sink");
|
||||
|
||||
|
@ -35,12 +36,22 @@ GST_START_TEST (test_sink)
|
|||
fail_unless (ret == GST_STATE_ASYNC, "no async state return");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_PLAYING);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "cannot force play");
|
||||
fail_unless (ret == GST_STATE_ASYNC, "no forced async state change");
|
||||
|
||||
ret = gst_element_get_state (sink, ¤t, &pending, NULL);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "not playing");
|
||||
fail_unless (current == GST_STATE_PLAYING, "not playing");
|
||||
fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
|
||||
GST_TIME_TO_TIMEVAL ((GstClockTime) 0, tv);
|
||||
|
||||
ret = gst_element_get_state (sink, ¤t, &pending, &tv);
|
||||
fail_unless (ret == GST_STATE_ASYNC, "not changing state async");
|
||||
fail_unless (current == GST_STATE_PAUSED, "bad current state");
|
||||
fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_PAUSED);
|
||||
fail_unless (ret == GST_STATE_ASYNC, "no async going back to paused");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_READY);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "failed to go to ready");
|
||||
|
||||
gst_object_unref (sink);
|
||||
}
|
||||
|
||||
GST_END_TEST
|
||||
|
|
|
@ -528,6 +528,9 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
basesink->preroll_queued,
|
||||
basesink->buffers_queued, basesink->events_queued);
|
||||
|
||||
if (basesink->playing_async)
|
||||
goto playing_async;
|
||||
|
||||
/* check if we are prerolling */
|
||||
if (!basesink->need_preroll)
|
||||
goto no_preroll;
|
||||
|
@ -626,6 +629,34 @@ no_preroll:
|
|||
ret = gst_base_sink_preroll_queue_empty (basesink, pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
return ret;
|
||||
}
|
||||
playing_async:
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
gint t;
|
||||
|
||||
basesink->have_preroll = FALSE;
|
||||
basesink->playing_async = FALSE;
|
||||
|
||||
/* handle buffer first */
|
||||
ret = gst_base_sink_preroll_queue_empty (basesink, pad);
|
||||
|
||||
/* unroll locks, commit state, reacquire stream lock */
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
t = GST_STREAM_UNLOCK_FULL (pad);
|
||||
GST_DEBUG ("released stream lock %d times", t);
|
||||
if (t <= 0) {
|
||||
GST_WARNING ("STREAM_LOCK should have been locked !!");
|
||||
g_warning ("STREAM_LOCK should have been locked !!");
|
||||
}
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_DEBUG ("commit state %p >", basesink);
|
||||
gst_element_commit_state (GST_ELEMENT (basesink));
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
if (t > 0)
|
||||
GST_STREAM_LOCK_FULL (pad, t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
flushing:
|
||||
|
@ -1104,11 +1135,18 @@ gst_base_sink_change_state (GstElement * element)
|
|||
* thread to do this. */
|
||||
if (basesink->eos) {
|
||||
gst_base_sink_preroll_queue_empty (basesink, basesink->sinkpad);
|
||||
} else if (!basesink->have_preroll) {
|
||||
/* don't need preroll, but do queue a commit_state */
|
||||
basesink->need_preroll = FALSE;
|
||||
basesink->playing_async = TRUE;
|
||||
ret = GST_STATE_ASYNC;
|
||||
/* we know it's not waiting, no need to signal */
|
||||
} else {
|
||||
/* don't need the preroll anymore */
|
||||
basesink->need_preroll = FALSE;
|
||||
/* now let it play */
|
||||
GST_PREROLL_SIGNAL (basesink->sinkpad);
|
||||
}
|
||||
/* don't need the preroll anymore */
|
||||
basesink->need_preroll = FALSE;
|
||||
/* now let it play */
|
||||
GST_PREROLL_SIGNAL (basesink->sinkpad);
|
||||
GST_PREROLL_UNLOCK (basesink->sinkpad);
|
||||
break;
|
||||
}
|
||||
|
@ -1133,6 +1171,8 @@ gst_base_sink_change_state (GstElement * element)
|
|||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
basesink->playing_async = FALSE;
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
|
|
@ -81,6 +81,7 @@ struct _GstBaseSink {
|
|||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
|
|
@ -1778,6 +1778,7 @@ gst_element_set_state (GstElement * element, GstElementState state)
|
|||
GST_STATE_FINAL (element) = state;
|
||||
if (ret == GST_STATE_ASYNC) {
|
||||
gst_element_commit_state (element);
|
||||
gst_element_lost_state (element);
|
||||
}
|
||||
|
||||
/* start with the current state */
|
||||
|
|
|
@ -528,6 +528,9 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
|
|||
basesink->preroll_queued,
|
||||
basesink->buffers_queued, basesink->events_queued);
|
||||
|
||||
if (basesink->playing_async)
|
||||
goto playing_async;
|
||||
|
||||
/* check if we are prerolling */
|
||||
if (!basesink->need_preroll)
|
||||
goto no_preroll;
|
||||
|
@ -626,6 +629,34 @@ no_preroll:
|
|||
ret = gst_base_sink_preroll_queue_empty (basesink, pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
return ret;
|
||||
}
|
||||
playing_async:
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
gint t;
|
||||
|
||||
basesink->have_preroll = FALSE;
|
||||
basesink->playing_async = FALSE;
|
||||
|
||||
/* handle buffer first */
|
||||
ret = gst_base_sink_preroll_queue_empty (basesink, pad);
|
||||
|
||||
/* unroll locks, commit state, reacquire stream lock */
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
t = GST_STREAM_UNLOCK_FULL (pad);
|
||||
GST_DEBUG ("released stream lock %d times", t);
|
||||
if (t <= 0) {
|
||||
GST_WARNING ("STREAM_LOCK should have been locked !!");
|
||||
g_warning ("STREAM_LOCK should have been locked !!");
|
||||
}
|
||||
GST_STATE_LOCK (basesink);
|
||||
GST_DEBUG ("commit state %p >", basesink);
|
||||
gst_element_commit_state (GST_ELEMENT (basesink));
|
||||
GST_STATE_UNLOCK (basesink);
|
||||
if (t > 0)
|
||||
GST_STREAM_LOCK_FULL (pad, t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
flushing:
|
||||
|
@ -1104,11 +1135,18 @@ gst_base_sink_change_state (GstElement * element)
|
|||
* thread to do this. */
|
||||
if (basesink->eos) {
|
||||
gst_base_sink_preroll_queue_empty (basesink, basesink->sinkpad);
|
||||
} else if (!basesink->have_preroll) {
|
||||
/* don't need preroll, but do queue a commit_state */
|
||||
basesink->need_preroll = FALSE;
|
||||
basesink->playing_async = TRUE;
|
||||
ret = GST_STATE_ASYNC;
|
||||
/* we know it's not waiting, no need to signal */
|
||||
} else {
|
||||
/* don't need the preroll anymore */
|
||||
basesink->need_preroll = FALSE;
|
||||
/* now let it play */
|
||||
GST_PREROLL_SIGNAL (basesink->sinkpad);
|
||||
}
|
||||
/* don't need the preroll anymore */
|
||||
basesink->need_preroll = FALSE;
|
||||
/* now let it play */
|
||||
GST_PREROLL_SIGNAL (basesink->sinkpad);
|
||||
GST_PREROLL_UNLOCK (basesink->sinkpad);
|
||||
break;
|
||||
}
|
||||
|
@ -1133,6 +1171,8 @@ gst_base_sink_change_state (GstElement * element)
|
|||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
basesink->playing_async = FALSE;
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
|
|
@ -81,6 +81,7 @@ struct _GstBaseSink {
|
|||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
|
|
@ -28,6 +28,7 @@ GST_START_TEST (test_sink)
|
|||
GstElement *sink;
|
||||
GstElementStateReturn ret;
|
||||
GstElementState current, pending;
|
||||
GTimeVal tv;
|
||||
|
||||
sink = gst_element_factory_make ("fakesink", "sink");
|
||||
|
||||
|
@ -35,12 +36,22 @@ GST_START_TEST (test_sink)
|
|||
fail_unless (ret == GST_STATE_ASYNC, "no async state return");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_PLAYING);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "cannot force play");
|
||||
fail_unless (ret == GST_STATE_ASYNC, "no forced async state change");
|
||||
|
||||
ret = gst_element_get_state (sink, ¤t, &pending, NULL);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "not playing");
|
||||
fail_unless (current == GST_STATE_PLAYING, "not playing");
|
||||
fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
|
||||
GST_TIME_TO_TIMEVAL ((GstClockTime) 0, tv);
|
||||
|
||||
ret = gst_element_get_state (sink, ¤t, &pending, &tv);
|
||||
fail_unless (ret == GST_STATE_ASYNC, "not changing state async");
|
||||
fail_unless (current == GST_STATE_PAUSED, "bad current state");
|
||||
fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_PAUSED);
|
||||
fail_unless (ret == GST_STATE_ASYNC, "no async going back to paused");
|
||||
|
||||
ret = gst_element_set_state (sink, GST_STATE_READY);
|
||||
fail_unless (ret == GST_STATE_SUCCESS, "failed to go to ready");
|
||||
|
||||
gst_object_unref (sink);
|
||||
}
|
||||
|
||||
GST_END_TEST
|
||||
|
|
Loading…
Reference in a new issue