From 737e7dcc396352966dbc075f62aed2b5b16ae257 Mon Sep 17 00:00:00 2001 From: Ganesh prasad Sahu Date: Mon, 15 Jun 2026 04:54:58 +0000 Subject: [PATCH] =?UTF-8?q?Queue=20frames=20till=20Video=20Frame=20Observe?= =?UTF-8?q?r=20is=20ready=20https://bugs.webkit.org/show=5Fbug.cgi=3Fid=3D?= =?UTF-8?q?317111=20Reviewed=20by:=20E.=20Oca=C3=B1a=20Gonz=C3=A1lez?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem : WebRTC playback doesnot recover from a black screen and the issue is seen Intermittently Cause: The first video frame(s) (containing SPS/PPS/IDR) being dropped because libwebrtc starts delivering decoded frames before the downstream GStreamer pipeline's InternalSource registers as a VideoFrameObserver. Without first having the SPS/PPS and the first sync frame , the decoder can not decode any subsequent delta frames. In Following code snippet from mediastream/gstreamer/GStreamerMediaStreamSource.cpp, frames received while m_isObserving is false might be dropped. void videoFrameAvailable(VideoFrame& videoFrame, VideoFrameTimeMetadata) final { return; updateFirstVideoSampleSeenFlag(); Change : While this patch doesnot address the root cause of delayed start of VideoFrameObserver, add a small frame buffer to hold frames (currently max size set to 30 frames) that arrive before any observer registers. deliver the frames when observer is registered Note: From tests it is observed that only the first frame or 2 is actually needed to be queued. * Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp: (RealtimeMediaSource::videoFrameAvailable) : Queue frames till observer is ready * Source/WebCore/platform/mediastream/RealtimeMediaSource.h: (struct PendingVideoFrame) : Added a buffer to hold the frames --- .../mediastream/RealtimeMediaSource.cpp | 19 +++++++++++++++++++ .../mediastream/RealtimeMediaSource.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp index 5ebc2b98ca639..935b8f8ee2bea 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp @@ -218,6 +218,25 @@ void RealtimeMediaSource::videoFrameAvailable(VideoFrame& videoFrame, VideoFrame updateHasStartedProducingData(); Locker locker { m_videoFrameObserversLock }; + if (m_videoFrameObservers.isEmpty()) { + if (m_pendingVideoFrames.size() < maxPendingVideoFramesBeforeAddTrack) { + m_pendingVideoFrames.append(PendingVideoFrame { &videoFrame, metadata }); + } + else { + WTFLogAlways("RealtimeMediaSource: Dropping video frame (queue is full) %zu frames", m_pendingVideoFrames.size()); + } + return; + } + if (!m_pendingVideoFrames.isEmpty()) { + WTFLogAlways("RealtimeMediaSource: Delivering %zu queued frame(s) (pipeline ready)", m_pendingVideoFrames.size()); + for (auto& pending : m_pendingVideoFrames) { + if (pending.frame) { + for (auto* obs : m_videoFrameObservers) + obs->videoFrameAvailable(*pending.frame, pending.metadata); + } + } + m_pendingVideoFrames.clear(); + } for (auto* observer : m_videoFrameObservers) observer->videoFrameAvailable(videoFrame, metadata); } diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h index 091aa0ead2afe..ffc3ad1007dc8 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h @@ -300,6 +300,13 @@ class WEBCORE_EXPORT RealtimeMediaSource mutable Lock m_videoFrameObserversLock; HashSet m_videoFrameObservers WTF_GUARDED_BY_LOCK(m_videoFrameObserversLock); + struct PendingVideoFrame { + RefPtr frame; + VideoFrameTimeMetadata metadata; + }; + static constexpr size_t maxPendingVideoFramesBeforeAddTrack = 30; + Vector m_pendingVideoFrames WTF_GUARDED_BY_LOCK(m_videoFrameObserversLock); + // Set on the main thread from constraints. IntSize m_size; // Set on sample generation thread.