Skip to content

Commit f57d880

Browse files
asurdej-comcasteocanha
authored andcommitted
[MSE][GStreamer] Make fake preroll asynchronous
https://bugs.webkit.org/show_bug.cgi?id=295289 Reviewed by Alicia Boya Garcia. With the current implementation the whole seek flow as executed in a single main loop cycle. As a result, the JS app had no chance to spot that video.seeking attribute is ever set to true. Also some apps listen to video.onseeking and expects that video.seeking attribute to be true in such case. That wasn't a valid assumption. Also, the behaviour isn't the same in <video> elements that are audio-only as in <audio> elements. This happens on the Amlogic platform, that doesn't have asynchronous state changes on its audio sink. Spotify is broken there because of this problem. See: #1232 #1527 This patch calls didPreroll() also for <video> elements that are audio-only. Also makes that call async by putting it on the HTML media element task queue to make sure it is executed after dispatching 'seeking' event to JS so the app has a chance to notice that HTMLmedia.seeking attribute is 'true'. Original author: Andrzej Surdej <101130014+asurdej-comcast@users.noreply.github.com> * Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: (WebCore::MediaPlayerPrivateGStreamerMSE::doSeek): Find the actual final audio sink. Call didPreroll() asynchronously for any media element having only audio. Canonical link: https://commits.webkit.org/298239@main
1 parent 23491c2 commit f57d880

1 file changed

Lines changed: 32 additions & 11 deletions

File tree

Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,20 +278,41 @@ bool MediaPlayerPrivateGStreamerMSE::doSeek(const SeekTarget& target, float rate
278278
m_mediaSourcePrivate->seekToTime(*result);
279279

280280
auto player = m_player.get();
281-
if (player && !player->isVideoPlayer() && m_audioSink) {
282-
gboolean audioSinkPerformsAsyncStateChanges;
283-
g_object_get(m_audioSink.get(), "async", &audioSinkPerformsAsyncStateChanges, nullptr);
281+
if (player && !hasVideo() && m_audioSink) {
282+
gboolean audioSinkPerformsAsyncStateChanges = true;
283+
284+
GRefPtr<GstElement> sink = m_audioSink;
285+
while (GST_IS_BIN(sink.get())) {
286+
GUniquePtr<GstIterator> iter(gst_bin_iterate_sinks(GST_BIN_CAST(sink.get())));
287+
GValue value = G_VALUE_INIT;
288+
auto result = gst_iterator_next(iter.get(), &value);
289+
ASSERT_UNUSED(result, result == GST_ITERATOR_OK);
290+
sink = GST_ELEMENT(g_value_get_object(&value));
291+
g_value_unset(&value);
292+
}
293+
if (gstObjectHasProperty(sink.get(), "async"))
294+
g_object_get(sink.get(), "async", &audioSinkPerformsAsyncStateChanges, nullptr);
284295
if (!audioSinkPerformsAsyncStateChanges) {
285296
// If audio-only pipeline's sink is not performing async state changes
286297
// we must simulate preroll right away as otherwise nothing will trigger it.
287-
bool mustPreventPositionReset = m_isWaitingForPreroll && m_isSeeking;
288-
if (mustPreventPositionReset)
289-
m_cachedPosition = currentTime();
290-
didPreroll();
291-
if (mustPreventPositionReset) {
292-
propagateReadyStateToPlayer();
293-
invalidateCachedPosition();
294-
}
298+
299+
// Post this on HTML media element queue so it will be executed
300+
// synchonously with media events (e.g. seeking). This will ensure
301+
// that HTML element attributes (like HTMLmedia.seeking) are not reseted
302+
// before app receives "seeking" event
303+
player->queueTaskOnEventLoop([this, weakThis = ThreadSafeWeakPtr { *this }] {
304+
RefPtr self = weakThis.get();
305+
if (!self)
306+
return;
307+
bool mustPreventPositionReset = m_isWaitingForPreroll && m_isSeeking;
308+
if (mustPreventPositionReset)
309+
m_cachedPosition = currentTime();
310+
didPreroll();
311+
if (mustPreventPositionReset) {
312+
propagateReadyStateToPlayer();
313+
invalidateCachedPosition();
314+
}
315+
});
295316
}
296317
}
297318
});

0 commit comments

Comments
 (0)