Add logging to WebRTC video pipeline to check for frame rate stability
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jun 2020 14:07:32 +0000 (14:07 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jun 2020 14:07:32 +0000 (14:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=213369

Reviewed by Eric Carlson.

Source/ThirdParty/libwebrtc:

Add logging for encoded frames taking a long time to be received.
We log the time take to receive the frame, the time since previous frame, the byte size of the frame.
We compute that a frame takes too long by checking whether it is delayed by more than three expected frames.

* Source/webrtc/video/rtp_video_stream_receiver.cc:
* Source/webrtc/video/rtp_video_stream_receiver.h:

Source/WebCore:

Add a FrameRateMonitor class to compute frame stability.
Use this class at end of the video pipeline (LocalSampleBufferDisplayLayer).
Log messages in case a frame gets frozen at LocalSampleBufferDisplayLayer time.
We compute that a frame takes too long by checking whether it is delayed by more than three expected frames.
This logging is complemented with encoded frame reception logging (at the beginning of the video pipeline)
and WebRTC stats logging (freezeCount, totalFreezeDuration, shortly after decoding the frames).

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/FrameRateMonitor.cpp: Added.
(WebCore::FrameRateMonitor::newFrame):
* platform/FrameRateMonitor.h: Added.
(WebCore::FrameRateMonitor::frameRate const):
(WebCore::FrameRateMonitor::frameCount const):
(WebCore::FrameRateMonitor::FrameRateMonitor):
* platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h:
* platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm:
(WebCore::LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer):
(WebCore::LocalSampleBufferDisplayLayer::enqueueSample):
(WebCore::LocalSampleBufferDisplayLayer::enqueueSampleBuffer):
(WebCore::LocalSampleBufferDisplayLayer::onFrameRateNotification):
* platform/mediastream/mac/AudioMediaStreamTrackRendererUnit.h:
Unified build fix.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@263453 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/ThirdParty/libwebrtc/ChangeLog
Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.cc
Source/ThirdParty/libwebrtc/Source/webrtc/video/rtp_video_stream_receiver.h
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/FrameRateMonitor.cpp [new file with mode: 0644]
Source/WebCore/platform/FrameRateMonitor.h [new file with mode: 0644]
Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h
Source/WebCore/platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm
Source/WebCore/platform/mediastream/mac/AudioMediaStreamTrackRendererUnit.h

index da97822..ad31a63 100644 (file)
@@ -1,3 +1,17 @@
+2020-06-24  Youenn Fablet  <youenn@apple.com>
+
+        Add logging to WebRTC video pipeline to check for frame rate stability
+        https://bugs.webkit.org/show_bug.cgi?id=213369
+
+        Reviewed by Eric Carlson.
+
+        Add logging for encoded frames taking a long time to be received.
+        We log the time take to receive the frame, the time since previous frame, the byte size of the frame.
+        We compute that a frame takes too long by checking whether it is delayed by more than three expected frames.
+
+        * Source/webrtc/video/rtp_video_stream_receiver.cc:
+        * Source/webrtc/video/rtp_video_stream_receiver.h:
+
 2020-06-22  Tim Horton  <timothy_horton@apple.com>
 
         libwebrtc fails to build on arm64
index 058df0a..79a69c7 100644 (file)
@@ -47,6 +47,7 @@
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
 #include "system_wrappers/include/ntp_time.h"
@@ -740,6 +741,32 @@ void RtpVideoStreamReceiver::OnAssembledFrame(
   RTC_DCHECK_RUN_ON(&network_tc_);
   RTC_DCHECK(frame);
 
+#if defined(WEBRTC_WEBKIT_BUILD)
+    static const unsigned MaxFrameDelayCount = 3;
+    static const unsigned TimeStampQueueDurationInMs = 2000;
+    static const unsigned OneSecondInMs = 1000;
+    // FIXME: Consider using MovingAverage instead.
+    ++frameCount_;
+
+    auto frameTime = clock_->TimeInMilliseconds();
+    auto lastFrameTime = observedFrameTimeStamps_.empty() ? frameTime : observedFrameTimeStamps_.back();
+
+    if (observedFrameRate_) {
+      auto delay = frameTime - lastFrameTime;
+      if (delay > (MaxFrameDelayCount * OneSecondInMs / observedFrameRate_)) {
+        RTC_LOG(LS_INFO) << "RtpVideoStreamReceiver::OnAssembledFrame at " << frameTime << ", previous frame was at " << lastFrameTime << ", observed frame rate is " << observedFrameRate_ << ", delay since last frame is " << (frameTime - lastFrameTime) <<  " ms, frame count is " << frameCount_ << ", size is " << frame->EncodedImage().size() << ", frame reception duration is " << (frame->video_timing().receive_finish_ms - frame->video_timing().receive_start_ms) << " ms, " << " observed samples count is " << observedFrameTimeStamps_.size() << ", observed samples duration is " << (observedFrameTimeStamps_.back() - observedFrameTimeStamps_.front());
+      }
+    }
+
+    observedFrameTimeStamps_.push_back(frameTime);
+    while (observedFrameTimeStamps_.front() <= (frameTime - TimeStampQueueDurationInMs))
+        observedFrameTimeStamps_.pop_front();
+
+    auto queueDuration = frameTime - observedFrameTimeStamps_.front();
+    if (queueDuration > OneSecondInMs)
+        observedFrameRate_ = observedFrameTimeStamps_.size() * OneSecondInMs / queueDuration;
+#endif
+
   const absl::optional<RTPVideoHeader::GenericDescriptorInfo>& descriptor =
       frame->GetRtpVideoHeader().generic;
 
index 330455b..37b27f3 100644 (file)
@@ -360,6 +360,12 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
 
   rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate>
       frame_transformer_delegate_;
+
+#if defined(WEBRTC_WEBKIT_BUILD)
+  std::deque<int64_t> observedFrameTimeStamps_;
+  double observedFrameRate_ { 0 };
+  uint64_t frameCount_ { 0 };
+#endif
 };
 
 }  // namespace webrtc
index 0ead6ea..263cdb2 100644 (file)
@@ -1,3 +1,34 @@
+2020-06-24  Youenn Fablet  <youenn@apple.com>
+
+        Add logging to WebRTC video pipeline to check for frame rate stability
+        https://bugs.webkit.org/show_bug.cgi?id=213369
+
+        Reviewed by Eric Carlson.
+
+        Add a FrameRateMonitor class to compute frame stability.
+        Use this class at end of the video pipeline (LocalSampleBufferDisplayLayer).
+        Log messages in case a frame gets frozen at LocalSampleBufferDisplayLayer time.
+        We compute that a frame takes too long by checking whether it is delayed by more than three expected frames.
+        This logging is complemented with encoded frame reception logging (at the beginning of the video pipeline)
+        and WebRTC stats logging (freezeCount, totalFreezeDuration, shortly after decoding the frames).
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/FrameRateMonitor.cpp: Added.
+        (WebCore::FrameRateMonitor::newFrame):
+        * platform/FrameRateMonitor.h: Added.
+        (WebCore::FrameRateMonitor::frameRate const):
+        (WebCore::FrameRateMonitor::frameCount const):
+        (WebCore::FrameRateMonitor::FrameRateMonitor):
+        * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.h:
+        * platform/graphics/avfoundation/objc/LocalSampleBufferDisplayLayer.mm:
+        (WebCore::LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer):
+        (WebCore::LocalSampleBufferDisplayLayer::enqueueSample):
+        (WebCore::LocalSampleBufferDisplayLayer::enqueueSampleBuffer):
+        (WebCore::LocalSampleBufferDisplayLayer::onFrameRateNotification):
+        * platform/mediastream/mac/AudioMediaStreamTrackRendererUnit.h:
+        Unified build fix.
+
 2020-06-24  Alexey Shvayka  <shvaikalesh@gmail.com>
 
         Remove [CallbackNeedsOperatorEqual] extended attribute
index d5c4e72..148f398 100644 (file)
@@ -1800,6 +1800,7 @@ platform/FileChooser.cpp
 platform/FileHandle.cpp
 platform/FileMonitor.cpp
 platform/FileStream.cpp
+platform/FrameRateMonitor.cpp
 platform/GenericTaskQueue.cpp
 platform/LayoutUnit.cpp
 platform/LegacySchemeRegistry.cpp
index 4e4fedc..af7db7a 100644 (file)
                418938B22429F9B4007FDC41 /* RetrieveRecordsOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 418938AF2429F9AB007FDC41 /* RetrieveRecordsOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                418A06D0133C04D500CD379C /* EventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 418A06CE133C04D500CD379C /* EventDispatcher.h */; };
                418F88050FF957AF0080F045 /* JSAbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 418F88030FF957AE0080F045 /* JSAbstractWorker.h */; };
+               4190F3A524A0B4EE00531C57 /* FrameRateMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4190F3A3249D152800531C57 /* FrameRateMonitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
                419242492127B93E00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 419242472127B7CC00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm */; };
                419ACF921F97E7DA009F1A83 /* ServiceWorkerFetch.h in Headers */ = {isa = PBXBuildFile; fileRef = 419ACF8E1F97E7D5009F1A83 /* ServiceWorkerFetch.h */; settings = {ATTRIBUTES = (Private, ); }; };
                419BC2DF1685329900D64D6D /* VisitedLinkState.h in Headers */ = {isa = PBXBuildFile; fileRef = 419BC2DD1685329900D64D6D /* VisitedLinkState.h */; };
                418C395F1C8F0AAB0051C8A3 /* ReadableStreamDefaultController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStreamDefaultController.h; sourceTree = "<group>"; };
                418F88020FF957AE0080F045 /* JSAbstractWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAbstractWorker.cpp; sourceTree = "<group>"; };
                418F88030FF957AE0080F045 /* JSAbstractWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAbstractWorker.h; sourceTree = "<group>"; };
+               4190F3A1249D152700531C57 /* FrameRateMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameRateMonitor.cpp; sourceTree = "<group>"; };
+               4190F3A3249D152800531C57 /* FrameRateMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameRateMonitor.h; sourceTree = "<group>"; };
                419242472127B7CC00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RealtimeOutgoingVideoSourceCocoa.mm; sourceTree = "<group>"; };
                41945694203502A5004BA277 /* ApplicationCacheResourceLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplicationCacheResourceLoader.cpp; sourceTree = "<group>"; };
                41945696203502A6004BA277 /* ApplicationCacheResourceLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationCacheResourceLoader.h; sourceTree = "<group>"; };
                                2EF1BFE9121C9F4200C27627 /* FileStream.h */,
                                2EF1BFF8121CB0CE00C27627 /* FileStreamClient.h */,
                                BC073BA90C399B1F000F5979 /* FloatConversion.h */,
+                               4190F3A1249D152700531C57 /* FrameRateMonitor.cpp */,
+                               4190F3A3249D152800531C57 /* FrameRateMonitor.h */,
                                CD4BE5291CE13425009D87DA /* GenericTaskQueue.cpp */,
                                CD62FB941AF018E70012ED7D /* GenericTaskQueue.h */,
                                A8748BDF12CBF2DC001FBA41 /* HashTools.h */,
                                93B77A380ADD792500EA4B81 /* FrameLoaderTypes.h in Headers */,
                                658436860AE01B7400E53753 /* FrameLoadRequest.h in Headers */,
                                628D214E12131EF40055DCFC /* FrameNetworkingContext.h in Headers */,
+                               4190F3A524A0B4EE00531C57 /* FrameRateMonitor.h in Headers */,
                                93309E0E099E64920056E581 /* FrameSelection.h in Headers */,
                                C4CD629B18383766007EBAF1 /* FrameSnapshotting.h in Headers */,
                                65A21485097A3F5300B9050A /* FrameTree.h in Headers */,
diff --git a/Source/WebCore/platform/FrameRateMonitor.cpp b/Source/WebCore/platform/FrameRateMonitor.cpp
new file mode 100644 (file)
index 0000000..3fbe16f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FrameRateMonitor.h"
+
+namespace WebCore {
+
+static constexpr Seconds MinimumAverageDuration = 1_s;
+static constexpr Seconds MaxQueueDuration = 2_s;
+static constexpr unsigned MaxFrameDelayCount = 3;
+
+void FrameRateMonitor::update()
+{
+    ++m_frameCount;
+
+    auto frameTime = MonotonicTime::now().secondsSinceEpoch().value();
+    auto lastFrameTime = m_observedFrameTimeStamps.isEmpty() ? frameTime : m_observedFrameTimeStamps.last();
+
+    if (m_observedFrameRate) {
+        auto maxDelay = MaxFrameDelayCount / m_observedFrameRate;
+        if ((frameTime - lastFrameTime) > maxDelay)
+            m_lateFrameCallback({ MonotonicTime::fromRawSeconds(frameTime), MonotonicTime::fromRawSeconds(lastFrameTime) });
+    }
+    m_observedFrameTimeStamps.append(frameTime);
+    m_observedFrameTimeStamps.removeAllMatching([&](auto time) {
+        return time <= frameTime - MaxQueueDuration.value();
+    });
+
+    auto queueDuration = m_observedFrameTimeStamps.last() - m_observedFrameTimeStamps.first();
+    if (queueDuration > MinimumAverageDuration.value())
+        m_observedFrameRate = (m_observedFrameTimeStamps.size() / queueDuration);
+}
+
+}
diff --git a/Source/WebCore/platform/FrameRateMonitor.h b/Source/WebCore/platform/FrameRateMonitor.h
new file mode 100644 (file)
index 0000000..bd8f854
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Deque.h>
+#include <wtf/MonotonicTime.h>
+
+namespace WebCore {
+
+class FrameRateMonitor {
+public:
+    struct LateFrameInfo {
+        MonotonicTime frameTime;
+        MonotonicTime lastFrameTime;
+    };
+    using LateFrameCallback = Function<void(LateFrameInfo)>;
+    explicit FrameRateMonitor(LateFrameCallback&&);
+
+    void update();
+
+    double observedFrameRate() const { return m_observedFrameRate; }
+    size_t frameCount() const { return m_frameCount; }
+
+private:
+    LateFrameCallback m_lateFrameCallback;
+    Deque<double, 120> m_observedFrameTimeStamps;
+    double m_observedFrameRate { 0 };
+    uint64_t m_frameCount { 0 };
+};
+
+inline FrameRateMonitor::FrameRateMonitor(LateFrameCallback&& callback)
+    : m_lateFrameCallback(WTFMove(callback))
+{
+}
+
+}
index bd6168f..92fa8c8 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 
+#include "FrameRateMonitor.h"
 #include "SampleBufferDisplayLayer.h"
 #include <wtf/Deque.h>
 #include <wtf/Forward.h>
@@ -81,6 +82,10 @@ private:
     void requestNotificationWhenReadyForVideoData();
     void enqueueSampleBuffer(MediaSample&);
 
+#if !RELEASE_LOG_DISABLED
+    void onIrregularFrameRateNotification(MonotonicTime frameTime, MonotonicTime lastFrameTime);
+#endif
+
 private:
     RetainPtr<WebAVSampleBufferStatusChangeListener> m_statusChangeListener;
     RetainPtr<AVSampleBufferDisplayLayer> m_sampleBufferDisplayLayer;
@@ -92,6 +97,10 @@ private:
     // Only accessed through m_processingQueue or if m_processingQueue is null.
     using PendingSampleQueue = Deque<Ref<MediaSample>>;
     PendingSampleQueue m_pendingVideoSampleQueue;
+
+#if !RELEASE_LOG_DISABLED
+    FrameRateMonitor m_frameRateMonitor;
+#endif
 };
 
 inline void LocalSampleBufferDisplayLayer::setRenderPolicy(RenderPolicy renderPolicy)
index 70b3c44..2984690 100644 (file)
@@ -153,6 +153,9 @@ LocalSampleBufferDisplayLayer::LocalSampleBufferDisplayLayer(RetainPtr<AVSampleB
     , m_statusChangeListener(adoptNS([[WebAVSampleBufferStatusChangeListener alloc] initWithParent:this]))
     , m_sampleBufferDisplayLayer(WTFMove(sampleBufferDisplayLayer))
     , m_processingQueue(WorkQueue::create("LocalSampleBufferDisplayLayer queue"))
+#if !RELEASE_LOG_DISABLED
+    , m_frameRateMonitor([this](auto info) { onIrregularFrameRateNotification(info.frameTime, info.lastFrameTime); })
+#endif
 {
 }
 
@@ -300,6 +303,7 @@ void LocalSampleBufferDisplayLayer::enqueueSample(MediaSample& sample)
 {
     m_processingQueue->dispatch([this, sample = makeRef(sample)] {
         if (![m_sampleBufferDisplayLayer isReadyForMoreMediaData]) {
+            WTFLogAlways("LocalSampleBufferDisplayLayer::enqueueSample not ready for more media data");
             addSampleToPendingQueue(sample);
             requestNotificationWhenReadyForVideoData();
             return;
@@ -324,7 +328,20 @@ void LocalSampleBufferDisplayLayer::enqueueSampleBuffer(MediaSample& sample)
     }
 
     [m_sampleBufferDisplayLayer enqueueSampleBuffer:sampleToEnqueue];
+
+#if !RELEASE_LOG_DISABLED
+    m_frameRateMonitor.update();
+#endif
+}
+
+#if !RELEASE_LOG_DISABLED
+void LocalSampleBufferDisplayLayer::onIrregularFrameRateNotification(MonotonicTime frameTime, MonotonicTime lastFrameTime)
+{
+    callOnMainThread([frameTime = frameTime.secondsSinceEpoch().value(), lastFrameTime = lastFrameTime.secondsSinceEpoch().value(), observedFrameRate = m_frameRateMonitor.observedFrameRate(), frameCount = m_frameRateMonitor.frameCount()] {
+        WTFLogAlways("LocalSampleBufferDisplayLayer::enqueueSampleBuffer at %f, previous frame was at %f, observed frame rate is %f, delay since last frame is %f ms, frame count is %lu", frameTime, lastFrameTime, observedFrameRate, (frameTime - lastFrameTime) * 1000, frameCount);
+    });
 }
+#endif
 
 void LocalSampleBufferDisplayLayer::removeOldSamplesFromPendingQueue()
 {
index f87564d..44076a5 100644 (file)
@@ -30,6 +30,8 @@
 #include <AudioToolbox/AudioToolbox.h>
 #include <CoreAudio/CoreAudioTypes.h>
 #include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
 
 namespace WebCore {