-
Notifications
You must be signed in to change notification settings - Fork 152
Description
When performing a seek operation, the HTMLMediaElement::finishSeek() call may be triggered too early, with a "seeked" event being raised to the app at a wrong time.
The attached app reproduces the issue: test.zip
Below are logs captured using the test app (logs starting with XXX are app specific logs):
[Log] XXX: Pause video at 3.833333 (test.html, line 19)
[Log] HTMLMediaElement::pause(DC6B46A3)
[Log] HTMLMediaElement::pauseInternal(DC6B46A3)
[Log] MediaElementSession::clientWillPausePlayback(DC6B46A3)
[Log] MediaElementSession::processClientWillPausePlayback(DC6B46A3) state = Playing
[Log] MediaElementSession::setState(DC6B46A3) Paused
[Log] PlatformMediaSessionManager::sessionWillEndPlayback(0) (DC6B46A3)
[Log] HTMLMediaElement::setAutoplayEventPlaybackState(DC6B46A3) None
[Log] HTMLMediaElement::updatePlayState(DC6B46A3) shouldBePlaying = false, playerPaused = false
[Log] HTMLMediaElement::updateMediaPlayer(DC6B46A3)
[Log] PlatformMediaSessionManager::sessionCanProduceAudioChanged(0)
[Log] HTMLMediaElement::updateMediaPlayer(DC6B46A3)
[Log] HTMLMediaElement::updateMediaPlayer(DC6B46A3)
[Log] HTMLMediaElement::updateMediaPlayer(DC6B46A3)
[Log] XXX: Seek video from 3.833333 to 303.833333 (test.html, line 35)
[Log] HTMLMediaElement::seek(DC6B46A3) – {value: 303.833333}
[Log] HTMLMediaElement::setNetworkState(DC6B46A3) new state = Loading, current state = NETWORK_IDLE
[Log] HTMLMediaElement::setReadyState(DC6B46A3) new state = HaveFutureData, current state = HAVE_ENOUGH_DATA
[Log] HTMLMediaElement::finishSeek(DC6B46A3) current time = – {value: 3.875, numerator: 3875000000, denominator: 1000000000, …}
[Log] XXX: onSeekedEvent - SEEKED. Current time: 3.875, duration: 596.473333333 (test.html, line 59)
The code sequence that causes this is as follows:
The seek triggers a call to MediaPlayerPrivateGStreamer::doSeek(), which calls updateBufferingStatus() before performing the seek at the gst pipeline level. The updateBufferingStatus() will call updateStates() just before exiting, which in turn notifies the player of a ready state change via the call to m_player->readyStateChanged(). HTMLMediaElement::setReadyState() will be called, which will evaluate the expression below:
if (m_seekRequested && !m_player->seeking() && m_readyState >= HAVE_CURRENT_DATA)
finishSeek();
The finishSeek() will be called, because the m_player->seeking() is still returning false, because the seeking state was not yet changed at the player level (m_isSeeking). It will be changed only after the doSeek() call returns, which has not happened yet
This seems to have been introduced with commit de3425a ("[GStreamer] Buffering hysteresis and buffering improvements for Broadcom")