Skip to content

Commit

Permalink
Cherry-pick 274730@main (f270bdb). https://bugs.webkit.org/show_bug.c…
Browse files Browse the repository at this point in the history
…gi?id=263317

    [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

Canonical link: https://commits.webkit.org/274313.169@webkitglib/2.44
  • Loading branch information
calvaris authored and aperezdc committed Apr 27, 2024
1 parent 4746fa7 commit 21a14e2
Showing 1 changed file with 32 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ void MediaPlayerPrivateGStreamer::prepareToPlay()

bool MediaPlayerPrivateGStreamer::isPipelineSeeking(GstState current, GstState pending, GstStateChangeReturn change) const
{
bool isSeeking = m_isSeeking && change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
return isSeeking;
return change == GST_STATE_CHANGE_ASYNC && current == GST_STATE_PAUSED && pending == GST_STATE_PAUSED;
}

bool MediaPlayerPrivateGStreamer::isPipelineSeeking() const
{
GstState current, pending;
Expand Down Expand Up @@ -472,19 +472,31 @@ bool MediaPlayerPrivateGStreamer::paused() const
return false;
}

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

if (isMediaStreamPlayer())
return isPipelinePaused;

bool paused = state <= GST_STATE_PAUSED;
// We also consider ourselves as paused if we are transitioning from playing to paused.
if (!paused && stateChange == GST_STATE_CHANGE_ASYNC)
paused = pending <= GST_STATE_PAUSED;
GST_LOG_OBJECT(pipeline(), "Paused: %s (state %s, pending %s, state change %s)", boolForPrinting(paused),
gst_element_state_get_name(state), gst_element_state_get_name(pending), gst_element_state_change_return_get_name(stateChange));
return paused;
#if !defined(GST_DISABLE_GST_DEBUG) || !defined(NDEBUG)
if (!isPipelineSeeking(state, pending, stateChange) && isPipelinePaused != !m_isPipelinePlaying
&& (stateChange == GST_STATE_CHANGE_SUCCESS || stateChange == GST_STATE_CHANGE_NO_PREROLL)) {
GST_WARNING_OBJECT(pipeline(), "states are not synchronized, player paused %s, pipeline paused %s",
boolForPrinting(!m_isPipelinePlaying), boolForPrinting(isPipelinePaused));
ASSERT_NOT_REACHED_WITH_MESSAGE("pipeline and player states are not synchronized");
}
#else
UNUSED_VARIABLE(stateChange);
#endif
#endif

GST_DEBUG_OBJECT(pipeline(), "paused %s", boolForPrinting(!m_isPipelinePlaying));
return !m_isPipelinePlaying;
}

bool MediaPlayerPrivateGStreamer::doSeek(const SeekTarget& target, float rate)
Expand Down Expand Up @@ -2678,6 +2690,14 @@ void MediaPlayerPrivateGStreamer::updateStates()
changePipelineState(GST_STATE_PLAYING);

m_networkState = MediaPlayer::NetworkState::Loading;

if (!isMediaStreamPlayer() && m_isLiveStream.value_or(false) && m_readyState < MediaPlayer::ReadyState::HaveEnoughData
&& m_currentState >= GST_STATE_PAUSED) {
GST_DEBUG_OBJECT(pipeline(), "live stream reached %s", gst_element_state_get_name(m_currentState));
m_readyState = MediaPlayer::ReadyState::HaveEnoughData;
if (player)
player->readyStateChanged();
}
break;
default:
GST_DEBUG_OBJECT(pipeline(), "Else : %d", getStateResult);
Expand Down

0 comments on commit 21a14e2

Please sign in to comment.