Skip to content

Commit 8eadcfb

Browse files
emutavchieocanha
authored andcommitted
[MSE][GStreamer] don't push samples while seeking
https://bugs.webkit.org/show_bug.cgi?id=295415 Reviewed by Alicia Boya Garcia. MediaSource::waitForTarget completes asynchronously. Even when the target time is already buffered, it still enqueues a task to compute seek time on next event loop cycle. This can lead to SourceBuffer providing media data for incorrect time, after GStreamer seek already flushed the source. For example this happens if TrackQueue::LowLevelHandler callback was posted just before the seek. The proposed change implements SourceBufferPrivate::isSeeking() that returns true until MSE seek is completed, effectivly blocking SourceBufferPrivate::provideMediaData during the seek. See: #1528 Original author: Eugene Mutavchi <Ievgen_Mutavchi@comcast.com> * Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: (WebCore::MediaPlayerPrivateGStreamerMSE::doSeek): Signal the seek intent to the media source private. * Source/WebCore/platform/graphics/gstreamer/mse/MediaSourcePrivateGStreamer.cpp: (WebCore::MediaSourcePrivateGStreamer::willSeek): Forward the seek intent to all SourceBufferPrivates. * Source/WebCore/platform/graphics/gstreamer/mse/MediaSourcePrivateGStreamer.h: Added willSeek(). * Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp: (WebCore::SourceBufferPrivateGStreamer::willSeek): Set m_isSeeking to true. (WebCore::SourceBufferPrivateGStreamer::isSeeking const): Return m_isSeeking value. (WebCore::SourceBufferPrivateGStreamer::seekToTime): Unset m_isSeeking and call the default SourceBufferPrivate seekToTime() implementation. * Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.h: Added willSeek(), isSeeking(), seekToTime() and the m_isSeeking flag (to signal that we're waiting for samples from the multiplatform layer after a seek has been initiated; unset once the samples are ready for the platform-specific layer). Canonical link: https://commits.webkit.org/298330@main
1 parent a710083 commit 8eadcfb

5 files changed

Lines changed: 35 additions & 0 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ bool MediaPlayerPrivateGStreamerMSE::doSeek(const SeekTarget& target, float rate
269269
// This will also add support for fastSeek once done (see webkit.org/b/260607)
270270
if (!m_mediaSourcePrivate)
271271
return false;
272+
m_mediaSourcePrivate->willSeek();
272273
m_mediaSourcePrivate->waitForTarget(target)->whenSettled(RunLoop::current(), [this, weakThis = ThreadSafeWeakPtr { *this }](auto&& result) {
273274
RefPtr self = weakThis.get();
274275
if (!self || !result)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ TrackID MediaSourcePrivateGStreamer::registerTrackId(TrackID preferredId)
205205
return assignedId;
206206
}
207207

208+
void MediaSourcePrivateGStreamer::willSeek()
209+
{
210+
for (auto* sourceBuffer : m_activeSourceBuffers)
211+
downcast<SourceBufferPrivateGStreamer>(sourceBuffer)->willSeek();
212+
}
213+
208214
bool MediaSourcePrivateGStreamer::unregisterTrackId(TrackID trackId)
209215
{
210216
ASSERT(isMainThread());

Source/WebCore/platform/graphics/gstreamer/mse/MediaSourcePrivateGStreamer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class MediaSourcePrivateGStreamer final : public MediaSourcePrivate
7777
TrackID registerTrackId(TrackID);
7878
bool unregisterTrackId(TrackID);
7979

80+
void willSeek();
81+
8082
#if !RELEASE_LOG_DISABLED
8183
const Logger& logger() const final { return m_logger; }
8284
ASCIILiteral logClassName() const override { return "MediaSourcePrivateGStreamer"_s; }

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,24 @@ size_t SourceBufferPrivateGStreamer::platformEvictionThreshold() const
403403
return evictionThreshold;
404404
}
405405

406+
void SourceBufferPrivateGStreamer::willSeek()
407+
{
408+
ALWAYS_LOG(LOGIDENTIFIER);
409+
m_seeking = true;
410+
}
411+
412+
bool SourceBufferPrivateGStreamer::isSeeking() const
413+
{
414+
return m_seeking;
415+
}
416+
417+
void SourceBufferPrivateGStreamer::seekToTime(const MediaTime& time)
418+
{
419+
m_seeking = false;
420+
// WebKit now has the samples to complete the seek and is about to enqueue them.
421+
SourceBufferPrivate::seekToTime(time);
422+
}
423+
406424
#undef GST_CAT_DEFAULT
407425

408426
} // namespace WebCore

Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ class SourceBufferPrivateGStreamer final : public SourceBufferPrivate, public Ca
9696
size_t platformMaximumBufferSize() const override;
9797
size_t platformEvictionThreshold() const final;
9898

99+
void willSeek();
100+
bool isSeeking() const final;
101+
void seekToTime(const MediaTime&) final;
102+
99103
private:
100104
friend class AppendPipeline;
101105

@@ -110,6 +114,10 @@ class SourceBufferPrivateGStreamer final : public SourceBufferPrivate, public Ca
110114
StdUnorderedMap<TrackID, RefPtr<MediaSourceTrackGStreamer>> m_tracks;
111115
std::optional<MediaPromise::Producer> m_appendPromise;
112116

117+
// Set while waiting for samples from the multiplatform layer after a seek has initiated.
118+
// Unset once the samples are ready for the platform-specific layer.
119+
bool m_seeking { false };
120+
113121
#if !RELEASE_LOG_DISABLED
114122
Ref<const Logger> m_logger;
115123
const void* m_logIdentifier;

0 commit comments

Comments
 (0)