Skip to content

Commit 4026673

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 dbaf240 commit 4026673

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

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

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,9 @@ void MediaPlayerPrivateGStreamer::prepareToPlay()
390390

391391
bool MediaPlayerPrivateGStreamer::isPipelineSeeking(GstState current, GstState pending, GstStateChangeReturn change) const
392392
{
393-
bool isSeeking = m_isSeeking && change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
394-
return isSeeking;
393+
return change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
395394
}
395+
396396
bool MediaPlayerPrivateGStreamer::isPipelineSeeking() const
397397
{
398398
GstState current, pending;
@@ -468,19 +468,31 @@ bool MediaPlayerPrivateGStreamer::paused() const
468468
return false;
469469
}
470470

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

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

486498
bool MediaPlayerPrivateGStreamer::doSeek(const SeekTarget& target, float rate)
@@ -2664,6 +2676,14 @@ void MediaPlayerPrivateGStreamer::updateStates()
26642676
changePipelineState(GST_STATE_PLAYING);
26652677

26662678
m_networkState = MediaPlayer::NetworkState::Loading;
2679+
2680+
if (!isMediaStreamPlayer() && m_isLiveStream.value_or(false) && m_readyState < MediaPlayer::ReadyState::HaveEnoughData
2681+
&& m_currentState >= GST_STATE_PAUSED) {
2682+
GST_DEBUG_OBJECT(pipeline(), "live stream reached %s", gst_element_state_get_name(m_currentState));
2683+
m_readyState = MediaPlayer::ReadyState::HaveEnoughData;
2684+
if (player)
2685+
player->readyStateChanged();
2686+
}
26672687
break;
26682688
default:
26692689
GST_DEBUG_OBJECT(pipeline(), "Else : %d", getStateResult);

0 commit comments

Comments
 (0)