Skip to content

Commit bb85314

Browse files
committed
[MSE][GStreamer] Pause after seek is not working
https://bugs.webkit.org/show_bug.cgi?id=263317 Reviewed by Philippe Normand. So far we are just asking the pipeline if we were paused or not but that does not work when the pipeline is transitioning or seeking. That creates desynchronization between the media element and the player. We now consider the pipeline in the final state while it is transitioning, as it can handle other requests while at it. We also need to force ready state change when the pipeline finishes the state change to paused or playing because the player will report state changes sooner. This changes won't apply to MediaStream because the dynamics of prerolling are much different. Fly by style change in isPipelineSeeking. * Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::isPipelineSeeking const): (WebCore::MediaPlayerPrivateGStreamer::paused const): (WebCore::MediaPlayerPrivateGStreamer::updateStates): Canonical link: https://commits.webkit.org/274730@main
1 parent eda256c commit bb85314

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,9 @@ void MediaPlayerPrivateGStreamer::prepareToPlay()
402402

403403
bool MediaPlayerPrivateGStreamer::isPipelineSeeking(GstState current, GstState pending, GstStateChangeReturn change) const
404404
{
405-
bool isSeeking = m_isSeeking && change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
406-
return isSeeking;
405+
return change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
407406
}
407+
408408
bool MediaPlayerPrivateGStreamer::isPipelineSeeking() const
409409
{
410410
GstState current, pending;
@@ -475,19 +475,31 @@ bool MediaPlayerPrivateGStreamer::paused() const
475475
return false;
476476
}
477477

478+
// For debug mode (either GStreamer of WebKit) we make some extra check to ensure there is no desynchronization
479+
// between pipeline and player. In the case of media stream, we just return the result of the pipeline as there are
480+
// nuances regarding the prerolling creating some regressions in the tests.
481+
#if !defined(GST_DISABLE_GST_DEBUG) || !defined(NDEBUG) || (defined(ENABLE_MEDIA_STREAM) && ENABLE_MEDIA_STREAM)
478482
GstState state, pending;
479483
auto stateChange = gst_element_get_state(m_pipeline.get(), &state, &pending, 0);
480-
bool isSeeking = isPipelineSeeking(state, pending, stateChange);
481-
if (isSeeking)
482-
return !m_isPipelinePlaying;
484+
bool isPipelinePaused = state <= GST_STATE_PAUSED;
485+
486+
if (isMediaStreamPlayer())
487+
return isPipelinePaused;
483488

484-
bool paused = state <= GST_STATE_PAUSED;
485-
// We also consider ourselves as paused if we are transitioning from playing to paused.
486-
if (!paused && stateChange == GST_STATE_CHANGE_ASYNC)
487-
paused = pending <= GST_STATE_PAUSED;
488-
GST_LOG_OBJECT(pipeline(), "Paused: %s (state %s, pending %s, state change %s)", boolForPrinting(paused),
489-
gst_element_state_get_name(state), gst_element_state_get_name(pending), gst_element_state_change_return_get_name(stateChange));
490-
return paused;
489+
#if !defined(GST_DISABLE_GST_DEBUG) || !defined(NDEBUG)
490+
if (!isPipelineSeeking(state, pending, stateChange) && isPipelinePaused != !m_isPipelinePlaying
491+
&& (stateChange == GST_STATE_CHANGE_SUCCESS || stateChange == GST_STATE_CHANGE_NO_PREROLL)) {
492+
GST_WARNING_OBJECT(pipeline(), "states are not synchronized, player paused %s, pipeline paused %s",
493+
boolForPrinting(!m_isPipelinePlaying), boolForPrinting(isPipelinePaused));
494+
ASSERT_NOT_REACHED_WITH_MESSAGE("pipeline and player states are not synchronized");
495+
}
496+
#else
497+
UNUSED_VARIABLE(stateChange);
498+
#endif
499+
#endif
500+
501+
GST_DEBUG_OBJECT(pipeline(), "paused %s", boolForPrinting(!m_isPipelinePlaying));
502+
return !m_isPipelinePlaying;
491503
}
492504

493505
bool MediaPlayerPrivateGStreamer::doSeek(const MediaTime& position, float rate, GstSeekFlags seekFlags)
@@ -2603,6 +2615,13 @@ void MediaPlayerPrivateGStreamer::updateStates()
26032615
changePipelineState(GST_STATE_PLAYING);
26042616

26052617
m_networkState = MediaPlayer::NetworkState::Loading;
2618+
2619+
if (!isMediaStreamPlayer() && m_isLiveStream.value_or(false) && m_readyState < MediaPlayer::ReadyState::HaveEnoughData
2620+
&& m_currentState >= GST_STATE_PAUSED) {
2621+
GST_DEBUG_OBJECT(pipeline(), "live stream reached %s", gst_element_state_get_name(m_currentState));
2622+
m_readyState = MediaPlayer::ReadyState::HaveEnoughData;
2623+
m_player->readyStateChanged();
2624+
}
26062625
break;
26072626
default:
26082627
GST_DEBUG_OBJECT(pipeline(), "Else : %d", getStateResult);

0 commit comments

Comments
 (0)