tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a28cad6403de2b85d603b709660c9c5a68c81670
parent 5962a8bd98d15ae7fb5b4d1a7dc28b0f9510c3e5
Author: Dan Baker <dbaker@mozilla.com>
Date:   Mon, 27 Oct 2025 11:38:39 -0600

Bug 1995393 - Vendor libwebrtc from dedf36cfdc

Upstream commit: https://webrtc.googlesource.com/src/+/dedf36cfdc2ec6e4ea9e0277e825eb08106105fe
    Avoid global clock in SamplesStatsCounter

    This forces all callers to provide a timestamp of when the stat was
    collected rather than invoking the global clock. The old methods are
    deprecated and will be removed in the future.

    Bug: webrtc:42223992
    Change-Id: Icd9dcaa77811278b2edf9862176c9754eec4e287
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/405500
    Reviewed-by: Artem Titov <titovartem@webrtc.org>
    Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
    Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
    Auto-Submit: Evan Shrubsole <eshr@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45413}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/api/numerics/BUILD.gn | 1+
Mthird_party/libwebrtc/api/numerics/samples_stats_counter.h | 1+
Mthird_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc | 23+++++++++++++----------
Mthird_party/libwebrtc/call/call_perf_tests.cc | 22++++++++++++++--------
Mthird_party/libwebrtc/modules/audio_processing/audio_processing_performance_unittest.cc | 3++-
Mthird_party/libwebrtc/moz-patch-stack/s0001.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0027.patch | 34+++++++++++++++++-----------------
Mthird_party/libwebrtc/moz-patch-stack/s0053.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0091.patch | 4++--
Mthird_party/libwebrtc/moz-patch-stack/s0094.patch | 6+++---
Mthird_party/libwebrtc/moz-patch-stack/s0102.patch | 4++--
Mthird_party/libwebrtc/moz-patch-stack/s0107.patch | 8++++----
Mthird_party/libwebrtc/rtc_base/BUILD.gn | 1+
Mthird_party/libwebrtc/rtc_base/numerics/event_rate_counter.cc | 2+-
Mthird_party/libwebrtc/rtc_base/numerics/sample_stats.cc | 19+++++++++++++++----
Mthird_party/libwebrtc/rtc_base/numerics/sample_stats.h | 7+++++++
Mthird_party/libwebrtc/rtc_tools/BUILD.gn | 1+
Mthird_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis.cc | 7+++++--
Mthird_party/libwebrtc/test/network/network_emulation.cc | 58+++++++++++++++++++++++++++++++++++++---------------------
Mthird_party/libwebrtc/test/network/network_emulation.h | 11++++++++++-
Mthird_party/libwebrtc/test/network/network_emulation_manager.cc | 22+++++++++++-----------
Mthird_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc | 43++++++++++++++++++++++++++-----------------
Mthird_party/libwebrtc/test/pc/e2e/analyzer/video/analyzing_video_sink.cc | 9++++++---
Mthird_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc | 32+++++++++++++++-----------------
Mthird_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc | 2+-
Mthird_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc | 22++++++++++++++--------
Mthird_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc | 11+++++++----
Mthird_party/libwebrtc/test/peer_scenario/peer_scenario.h | 2+-
Mthird_party/libwebrtc/test/scenario/performance_stats.cc | 7+++++--
Mthird_party/libwebrtc/test/scenario/scenario_unittest.cc | 3++-
Mthird_party/libwebrtc/test/scenario/stats_collection.cc | 105++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mthird_party/libwebrtc/test/scenario/stats_collection.h | 17++++++++++-------
Mthird_party/libwebrtc/test/scenario/stats_collection_unittest.cc | 9+++++----
Mthird_party/libwebrtc/test/testsupport/perf_test_unittest.cc | 13++++++++-----
Mthird_party/libwebrtc/video/video_analyzer.cc | 94++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
36 files changed, 387 insertions(+), 224 deletions(-)

diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor @@ -1,4 +1,4 @@ # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T17:36:04.672119+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T17:38:23.244502+00:00. # base of lastest vendoring -6da41c3e82 +dedf36cfdc diff --git a/third_party/libwebrtc/api/numerics/BUILD.gn b/third_party/libwebrtc/api/numerics/BUILD.gn @@ -35,6 +35,7 @@ if (rtc_include_tests) { deps = [ ":numerics", "../../test:test_support", + "../units:timestamp", "//third_party/abseil-cpp/absl/algorithm:container", ] } diff --git a/third_party/libwebrtc/api/numerics/samples_stats_counter.h b/third_party/libwebrtc/api/numerics/samples_stats_counter.h @@ -45,6 +45,7 @@ class SamplesStatsCounter { SamplesStatsCounter& operator=(SamplesStatsCounter&&); // Adds sample to the stats in amortized O(1) time. + [[deprecated("Use AddSample(StatsSample) instead.")]] void AddSample(double value); void AddSample(StatsSample sample); diff --git a/third_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc b/third_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc @@ -15,11 +15,14 @@ #include <vector> #include "absl/algorithm/container.h" +#include "api/units/timestamp.h" #include "test/gtest.h" namespace webrtc { namespace { +constexpr Timestamp kTimestamp = Timestamp::Seconds(1); + SamplesStatsCounter CreateStatsFilledWithIntsFrom1ToN(int n) { std::vector<double> data; for (int i = 1; i <= n; i++) { @@ -29,7 +32,7 @@ SamplesStatsCounter CreateStatsFilledWithIntsFrom1ToN(int n) { SamplesStatsCounter stats; for (double v : data) { - stats.AddSample(v); + stats.AddSample({.value = v, .time = kTimestamp}); } return stats; } @@ -43,7 +46,7 @@ SamplesStatsCounter CreateStatsFromUniformDistribution(int n, SamplesStatsCounter stats; for (int i = 1; i <= n; i++) { - stats.AddSample(dis(gen)); + stats.AddSample({.value = dis(gen), .time = kTimestamp}); } return stats; } @@ -71,10 +74,10 @@ TEST(SamplesStatsCounterTest, FullSimpleTest) { TEST(SamplesStatsCounterTest, VarianceAndDeviation) { SamplesStatsCounter stats; - stats.AddSample(2); - stats.AddSample(2); - stats.AddSample(-1); - stats.AddSample(5); + stats.AddSample({.value = 2, .time = kTimestamp}); + stats.AddSample({.value = 2, .time = kTimestamp}); + stats.AddSample({.value = -1, .time = kTimestamp}); + stats.AddSample({.value = 5, .time = kTimestamp}); EXPECT_DOUBLE_EQ(stats.GetAverage(), 2.0); EXPECT_DOUBLE_EQ(stats.GetVariance(), 4.5); @@ -117,7 +120,7 @@ TEST(SamplesStatsCounterTest, NumericStabilityForVariance) { } TEST_P(SamplesStatsCounterTest, AddSamples) { - int data[SIZE_FOR_MERGE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + double data[SIZE_FOR_MERGE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Split the data in different partitions. // We have 11 distinct tests: // * Empty merged with full sequence. @@ -128,10 +131,10 @@ TEST_P(SamplesStatsCounterTest, AddSamples) { // All must lead to the same result. SamplesStatsCounter stats0, stats1; for (int i = 0; i < GetParam(); ++i) { - stats0.AddSample(data[i]); + stats0.AddSample({.value = data[i], .time = kTimestamp}); } for (int i = GetParam(); i < SIZE_FOR_MERGE; ++i) { - stats1.AddSample(data[i]); + stats1.AddSample({.value = data[i], .time = kTimestamp}); } stats0.AddSamples(stats1); @@ -192,7 +195,7 @@ TEST(SamplesStatsCounterTest, MultiplyLeft) { TEST(SamplesStatsCounterTest, Divide) { SamplesStatsCounter stats; for (int i = 1; i <= 10; i++) { - stats.AddSample(i * 10); + stats.AddSample({.value = i * 10., .time = kTimestamp}); } EXPECT_TRUE(!stats.IsEmpty()); diff --git a/third_party/libwebrtc/call/call_perf_tests.cc b/third_party/libwebrtc/call/call_perf_tests.cc @@ -160,15 +160,15 @@ class VideoRtcpAndSyncObserver : public test::RtpRtcpObserver, if (stats.sync_offset_ms == std::numeric_limits<int>::max()) return; - int64_t now_ms = clock_->TimeInMilliseconds(); - int64_t time_since_creation = now_ms - creation_time_ms_; + Timestamp now = clock_->CurrentTime(); + int64_t time_since_creation = now.ms() - creation_time_ms_; // During the first couple of seconds audio and video can falsely be // estimated as being synchronized. We don't want to trigger on those. if (time_since_creation < kStartupTimeMs) return; if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) { if (first_time_in_sync_ == -1) { - first_time_in_sync_ = now_ms; + first_time_in_sync_ = now.ms(); GetGlobalMetricsLogger()->LogSingleValueMetric( "sync_convergence_time" + test_label_, "synchronization", time_since_creation, Unit::kMilliseconds, @@ -178,7 +178,8 @@ class VideoRtcpAndSyncObserver : public test::RtpRtcpObserver, observation_complete_.Set(); } if (first_time_in_sync_ != -1) - sync_offset_ms_list_.AddSample(stats.sync_offset_ms); + sync_offset_ms_list_.AddSample( + {.value = static_cast<double>(stats.sync_offset_ms), .time = now}); } void set_receive_stream(VideoReceiveStreamInterface* receive_stream) { @@ -545,9 +546,11 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { static const int kAcceptableBitrateErrorMargin = 15; // +- 7 class BitrateObserver : public test::EndToEndTest { public: - explicit BitrateObserver(bool using_min_transmit_bitrate, + explicit BitrateObserver(const Environment& env, + bool using_min_transmit_bitrate, TaskQueueBase* task_queue) : EndToEndTest(test::VideoTestConstants::kLongTimeout), + env_(env), send_stream_(nullptr), converged_(false), pad_to_min_bitrate_(using_min_transmit_bitrate), @@ -582,7 +585,9 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { observation_complete_.Set(); } if (converged_) - bitrate_kbps_list_.AddSample(bitrate_kbps); + bitrate_kbps_list_.AddSample( + {.value = static_cast<double>(bitrate_kbps), + .time = env_.clock().CurrentTime()}); } })); return SEND_PACKET; @@ -617,6 +622,7 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { ImprovementDirection::kNeitherIsBetter); } + Environment env_; VideoSendStream* send_stream_; bool converged_; const bool pad_to_min_bitrate_; @@ -626,7 +632,7 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { SamplesStatsCounter bitrate_kbps_list_; TaskQueueBase* task_queue_; scoped_refptr<PendingTaskSafetyFlag> task_safety_flag_; - } test(pad_to_min_bitrate, task_queue()); + } test(env(), pad_to_min_bitrate, task_queue()); fake_encoder_max_bitrate_ = kMaxEncodeBitrateKbps; RunBaseTest(&test); @@ -1025,7 +1031,7 @@ void CallPerfTest::TestEncodeFramerate(VideoEncoderFactory* encoder_factory, VideoSendStream::Stats stats = send_stream_->GetStats(); for (const auto& stat : stats.substreams) { encode_frame_rate_lists_[stat.first].AddSample( - stat.second.encode_frame_rate); + {.value = stat.second.encode_frame_rate, .time = now}); } if (now - start_time_ > kMinRunTime) { VerifyStats(); diff --git a/third_party/libwebrtc/modules/audio_processing/audio_processing_performance_unittest.cc b/third_party/libwebrtc/modules/audio_processing/audio_processing_performance_unittest.cc @@ -234,7 +234,8 @@ class TimedThreadApiProcessor { void AddDuration(int64_t duration) { if (samples_count_ >= kNumInitializationFrames && samples_count_ < num_durations_to_store_) { - api_call_durations_.AddSample(duration); + api_call_durations_.AddSample({.value = static_cast<double>(duration), + .time = clock_->CurrentTime()}); } samples_count_++; } diff --git a/third_party/libwebrtc/moz-patch-stack/s0001.patch b/third_party/libwebrtc/moz-patch-stack/s0001.patch @@ -1383,7 +1383,7 @@ index 5ccc3d7d38..cd957416bc 100644 const bool enable_svc_for_simulcast_; std::optional<SimulcastToSvcConverter> simulcast_to_svc_converter_; diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 62268d946d..9744edba44 100644 +index b806050fca..66b76b8c78 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -449,6 +449,12 @@ rtc_library("logging") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0027.patch b/third_party/libwebrtc/moz-patch-stack/s0027.patch @@ -1013,7 +1013,7 @@ index 39aa39a41c..b26e30e8bb 100644 "/config/external/nspr", "/nsprpub/lib/ds", diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 9744edba44..4114dc96e5 100644 +index 66b76b8c78..f88a45d683 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -326,6 +326,7 @@ rtc_library("sample_counter") { @@ -1032,7 +1032,7 @@ index 9744edba44..4114dc96e5 100644 rtc_library("zero_memory") { visibility = [ "*" ] -@@ -804,7 +806,9 @@ rtc_library("rtc_json") { +@@ -805,7 +807,9 @@ rtc_library("rtc_json") { "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/strings:string_view", ] @@ -1042,7 +1042,7 @@ index 9744edba44..4114dc96e5 100644 if (rtc_build_json) { deps += [ "//third_party/jsoncpp" ] } else { -@@ -1178,6 +1182,7 @@ if (!build_with_chromium) { +@@ -1179,6 +1183,7 @@ if (!build_with_chromium) { } rtc_library("network") { @@ -1050,7 +1050,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "network.cc", -@@ -1219,16 +1224,20 @@ rtc_library("network") { +@@ -1220,16 +1225,20 @@ rtc_library("network") { deps += [ ":win32" ] } } @@ -1071,7 +1071,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "net_helper.cc", -@@ -1239,8 +1248,10 @@ rtc_library("net_helper") { +@@ -1240,8 +1249,10 @@ rtc_library("net_helper") { "//third_party/abseil-cpp/absl/strings:string_view", ] } @@ -1082,7 +1082,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "socket_adapters.cc", -@@ -1261,6 +1272,7 @@ rtc_library("socket_adapters") { +@@ -1262,6 +1273,7 @@ rtc_library("socket_adapters") { "//third_party/abseil-cpp/absl/strings:string_view", ] } @@ -1090,7 +1090,7 @@ index 9744edba44..4114dc96e5 100644 rtc_library("network_route") { sources = [ -@@ -1275,6 +1287,7 @@ rtc_library("network_route") { +@@ -1276,6 +1288,7 @@ rtc_library("network_route") { } rtc_library("async_tcp_socket") { @@ -1098,7 +1098,7 @@ index 9744edba44..4114dc96e5 100644 sources = [ "async_tcp_socket.cc", "async_tcp_socket.h", -@@ -1294,8 +1307,10 @@ rtc_library("async_tcp_socket") { +@@ -1295,8 +1308,10 @@ rtc_library("async_tcp_socket") { "network:sent_packet", ] } @@ -1109,7 +1109,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "async_udp_socket.cc", -@@ -1319,8 +1334,10 @@ rtc_library("async_udp_socket") { +@@ -1320,8 +1335,10 @@ rtc_library("async_udp_socket") { "system:no_unique_address", ] } @@ -1120,7 +1120,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "async_packet_socket.cc", -@@ -1343,6 +1360,7 @@ rtc_library("async_packet_socket") { +@@ -1344,6 +1361,7 @@ rtc_library("async_packet_socket") { "//third_party/abseil-cpp/absl/functional:any_invocable", ] } @@ -1128,7 +1128,7 @@ index 9744edba44..4114dc96e5 100644 if (rtc_include_tests) { rtc_library("async_packet_socket_unittest") { -@@ -1428,6 +1446,7 @@ rtc_library("data_rate_limiter") { +@@ -1429,6 +1447,7 @@ rtc_library("data_rate_limiter") { } rtc_library("unique_id_generator") { @@ -1136,7 +1136,7 @@ index 9744edba44..4114dc96e5 100644 sources = [ "unique_id_generator.cc", "unique_id_generator.h", -@@ -1445,6 +1464,7 @@ rtc_library("unique_id_generator") { +@@ -1446,6 +1465,7 @@ rtc_library("unique_id_generator") { "//third_party/abseil-cpp/absl/strings:string_view", ] } @@ -1144,7 +1144,7 @@ index 9744edba44..4114dc96e5 100644 rtc_library("crc32") { sources = [ -@@ -1476,6 +1496,7 @@ rtc_library("stream") { +@@ -1477,6 +1497,7 @@ rtc_library("stream") { } rtc_library("rtc_certificate_generator") { @@ -1152,7 +1152,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "rtc_certificate_generator.cc", -@@ -1490,6 +1511,7 @@ rtc_library("rtc_certificate_generator") { +@@ -1491,6 +1512,7 @@ rtc_library("rtc_certificate_generator") { "//third_party/abseil-cpp/absl/functional:any_invocable", ] } @@ -1160,7 +1160,7 @@ index 9744edba44..4114dc96e5 100644 rtc_source_set("ssl_header") { visibility = [ "*" ] -@@ -1546,6 +1568,7 @@ rtc_library("crypto_random") { +@@ -1547,6 +1569,7 @@ rtc_library("crypto_random") { } rtc_library("ssl") { @@ -1168,7 +1168,7 @@ index 9744edba44..4114dc96e5 100644 visibility = [ "*" ] sources = [ "openssl_key_pair.cc", -@@ -1618,6 +1641,7 @@ rtc_library("ssl") { +@@ -1619,6 +1642,7 @@ rtc_library("ssl") { deps += [ ":win32" ] } } @@ -1176,7 +1176,7 @@ index 9744edba44..4114dc96e5 100644 rtc_library("ssl_adapter") { visibility = [ "*" ] -@@ -2341,7 +2365,7 @@ if (rtc_include_tests) { +@@ -2342,7 +2366,7 @@ if (rtc_include_tests) { } } diff --git a/third_party/libwebrtc/moz-patch-stack/s0053.patch b/third_party/libwebrtc/moz-patch-stack/s0053.patch @@ -29,7 +29,7 @@ index 7db75d5fd3..d0feb5007c 100644 rtc_library("task_queue_test") { visibility = [ "*" ] diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 4114dc96e5..3feb70a0d1 100644 +index f88a45d683..4e6b30a721 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -664,10 +664,14 @@ if (is_mac || is_ios) { diff --git a/third_party/libwebrtc/moz-patch-stack/s0091.patch b/third_party/libwebrtc/moz-patch-stack/s0091.patch @@ -13,10 +13,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/4e7b3c485e549e7e3 1 file changed, 6 insertions(+) diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 3feb70a0d1..3196d1fd22 100644 +index 4e6b30a721..731aa89c4c 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn -@@ -991,6 +991,12 @@ rtc_library("threading") { +@@ -992,6 +992,12 @@ rtc_library("threading") { "thread.cc", "thread.h", ] diff --git a/third_party/libwebrtc/moz-patch-stack/s0094.patch b/third_party/libwebrtc/moz-patch-stack/s0094.patch @@ -9,10 +9,10 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/ee2f06666bcc6d22c 1 file changed, 2 insertions(+) diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 3196d1fd22..9d319d5326 100644 +index 731aa89c4c..aca465a29f 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn -@@ -1654,6 +1654,7 @@ if (!build_with_mozilla) { +@@ -1655,6 +1655,7 @@ if (!build_with_mozilla) { } rtc_library("ssl_adapter") { @@ -20,7 +20,7 @@ index 3196d1fd22..9d319d5326 100644 visibility = [ "*" ] sources = [ "openssl_adapter.cc", -@@ -1702,6 +1703,7 @@ rtc_library("ssl_adapter") { +@@ -1703,6 +1704,7 @@ rtc_library("ssl_adapter") { configs += [ "..:external_ssl_library" ] } } diff --git a/third_party/libwebrtc/moz-patch-stack/s0102.patch b/third_party/libwebrtc/moz-patch-stack/s0102.patch @@ -616,7 +616,7 @@ index f48ba6e784..1122d4b66e 100644 if (rtc_build_libsrtp) { diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 9d319d5326..9653fd651f 100644 +index aca465a29f..8309bcaadc 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -9,8 +9,8 @@ @@ -630,7 +630,7 @@ index 9d319d5326..9653fd651f 100644 } rtc_source_set("protobuf_utils") { -@@ -1894,8 +1894,8 @@ if (!rtc_rusty_base64) { +@@ -1895,8 +1895,8 @@ if (!rtc_rusty_base64) { ] } } else { diff --git a/third_party/libwebrtc/moz-patch-stack/s0107.patch b/third_party/libwebrtc/moz-patch-stack/s0107.patch @@ -116,10 +116,10 @@ index e50b924806..ac722ddda3 100644 public_configs = [] if (!build_with_chromium) { diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn -index 9653fd651f..82b050a559 100644 +index 8309bcaadc..c99788fbef 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn -@@ -1533,6 +1533,7 @@ rtc_source_set("ssl_header") { +@@ -1534,6 +1534,7 @@ rtc_source_set("ssl_header") { } rtc_library("digest") { @@ -127,7 +127,7 @@ index 9653fd651f..82b050a559 100644 visibility = [ "*" ] sources = [ "message_digest.cc", -@@ -1554,8 +1555,10 @@ rtc_library("digest") { +@@ -1555,8 +1556,10 @@ rtc_library("digest") { configs += [ "..:external_ssl_library" ] } } @@ -138,7 +138,7 @@ index 9653fd651f..82b050a559 100644 visibility = [ "*" ] sources = [ "crypto_random.cc", -@@ -1576,6 +1579,7 @@ rtc_library("crypto_random") { +@@ -1577,6 +1580,7 @@ rtc_library("crypto_random") { configs += [ "..:external_ssl_library" ] } } diff --git a/third_party/libwebrtc/rtc_base/BUILD.gn b/third_party/libwebrtc/rtc_base/BUILD.gn @@ -784,6 +784,7 @@ rtc_library("rtc_stats_counters") { "../api/units:data_rate", "../api/units:time_delta", "../api/units:timestamp", + "../system_wrappers", ] } diff --git a/third_party/libwebrtc/rtc_base/numerics/event_rate_counter.cc b/third_party/libwebrtc/rtc_base/numerics/event_rate_counter.cc @@ -19,7 +19,7 @@ namespace webrtc { void EventRateCounter::AddEvent(Timestamp event_time) { if (first_time_.IsFinite()) - interval_.AddSample(event_time - last_time_); + interval_.AddSample(event_time - last_time_, event_time); first_time_ = std::min(first_time_, event_time); last_time_ = std::max(last_time_, event_time); event_count_++; diff --git a/third_party/libwebrtc/rtc_base/numerics/sample_stats.cc b/third_party/libwebrtc/rtc_base/numerics/sample_stats.cc @@ -13,7 +13,9 @@ #include "api/units/data_rate.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "rtc_base/checks.h" +#include "system_wrappers/include/clock.h" namespace webrtc { @@ -59,9 +61,14 @@ int SampleStats<double>::Count() { return static_cast<int>(GetSamples().size()); } +void SampleStats<TimeDelta>::AddSample(TimeDelta delta, Timestamp time) { + RTC_DCHECK(delta.IsFinite()); + stats_.AddSample({.value = delta.seconds<double>(), .time = time}); +} + void SampleStats<TimeDelta>::AddSample(TimeDelta delta) { RTC_DCHECK(delta.IsFinite()); - stats_.AddSample(delta.seconds<double>()); + AddSample(delta, Clock::GetRealTimeClock()->CurrentTime()); } void SampleStats<TimeDelta>::AddSampleMs(double delta_ms) { @@ -107,12 +114,16 @@ int SampleStats<TimeDelta>::Count() { return stats_.Count(); } -void SampleStats<DataRate>::AddSample(DataRate sample) { - stats_.AddSample(sample.bps<double>()); +void SampleStats<DataRate>::AddSample(DataRate rate, Timestamp time) { + stats_.AddSample({.value = rate.bps<double>(), .time = time}); +} + +void SampleStats<DataRate>::AddSample(DataRate rate) { + AddSample(rate, Clock::GetRealTimeClock()->CurrentTime()); } void SampleStats<DataRate>::AddSampleBps(double rate_bps) { - stats_.AddSample(rate_bps); + AddSample(DataRate::BitsPerSec(rate_bps)); } void SampleStats<DataRate>::AddSamples(const SampleStats<DataRate>& other) { diff --git a/third_party/libwebrtc/rtc_base/numerics/sample_stats.h b/third_party/libwebrtc/rtc_base/numerics/sample_stats.h @@ -13,6 +13,7 @@ #include "api/numerics/samples_stats_counter.h" #include "api/units/data_rate.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" namespace webrtc { template <typename T> @@ -35,7 +36,10 @@ class SampleStats<double> : public SamplesStatsCounter { template <> class SampleStats<TimeDelta> { public: + void AddSample(TimeDelta delta, Timestamp time); + [[deprecated("Use AddSample(TimeDelta, Timestamp) instead.")]] void AddSample(TimeDelta delta); + [[deprecated("Use AddSample(TimeDelta, Timestamp) instead.")]] void AddSampleMs(double delta_ms); void AddSamples(const SampleStats<TimeDelta>& other); bool IsEmpty(); @@ -55,7 +59,10 @@ class SampleStats<TimeDelta> { template <> class SampleStats<DataRate> { public: + void AddSample(DataRate rate, Timestamp time); + [[deprecated("Use AddSample(DataRate, Timestamp) instead.")]] void AddSample(DataRate rate); + [[deprecated("Use AddSample(DataRate, Timestamp) instead.")]] void AddSampleBps(double rate_bps); void AddSamples(const SampleStats<DataRate>& other); bool IsEmpty(); diff --git a/third_party/libwebrtc/rtc_tools/BUILD.gn b/third_party/libwebrtc/rtc_tools/BUILD.gn @@ -104,6 +104,7 @@ rtc_library("video_quality_analysis") { "../api/numerics", "../api/test/metrics:metric", "../api/test/metrics:metrics_logger", + "../api/units:timestamp", "../api/video:video_frame", "../api/video:video_rtp_headers", "../common_video", diff --git a/third_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis.cc b/third_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis.cc @@ -19,6 +19,7 @@ #include "api/scoped_refptr.h" #include "api/test/metrics/metric.h" #include "api/test/metrics/metrics_logger.h" +#include "api/units/timestamp.h" #include "api/video/video_frame_buffer.h" #include "rtc_base/checks.h" #include "rtc_tools/video_file_reader.h" @@ -133,8 +134,10 @@ void PrintAnalysisResults(const std::string& label, SamplesStatsCounter psnr_values; SamplesStatsCounter ssim_values; for (const auto& frame : results.frames) { - psnr_values.AddSample(frame.psnr_value); - ssim_values.AddSample(frame.ssim_value); + psnr_values.AddSample( + {.value = frame.psnr_value, .time = Timestamp::Zero()}); + ssim_values.AddSample( + {.value = frame.ssim_value, .time = Timestamp::Zero()}); } logger.LogMetric("PSNR_dB", label, psnr_values, Unit::kUnitless, diff --git a/third_party/libwebrtc/test/network/network_emulation.cc b/third_party/libwebrtc/test/network/network_emulation.cc @@ -58,9 +58,10 @@ EmulatedNetworkOutgoingStats GetOverallOutgoingStats( } EmulatedNetworkIncomingStats GetOverallIncomingStats( + Clock& clock, const std::map<IPAddress, EmulatedNetworkIncomingStats>& incoming_stats, EmulatedNetworkStatsGatheringMode mode) { - EmulatedNetworkIncomingStatsBuilder builder(mode); + EmulatedNetworkIncomingStatsBuilder builder(clock, mode); for (const auto& entry : incoming_stats) { builder.AddIncomingStats(entry.second); } @@ -100,7 +101,9 @@ void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent( stats_.bytes_sent += DataSize::Bytes(packet.ip_packet_size()); stats_.ecn_count.Add(packet.ecn); if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) { - stats_.sent_packets_size.AddSample(packet.ip_packet_size()); + stats_.sent_packets_size.AddSample( + {.value = static_cast<double>(packet.ip_packet_size()), + .time = sent_time}); } } @@ -127,8 +130,9 @@ EmulatedNetworkOutgoingStats EmulatedNetworkOutgoingStatsBuilder::Build() } EmulatedNetworkIncomingStatsBuilder::EmulatedNetworkIncomingStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode) - : stats_gathering_mode_(stats_gathering_mode) { + : clock_(clock), stats_gathering_mode_(stats_gathering_mode) { sequence_checker_.Detach(); } @@ -138,7 +142,8 @@ void EmulatedNetworkIncomingStatsBuilder::OnPacketDropped( stats_.packets_discarded_no_receiver++; stats_.bytes_discarded_no_receiver += packet_size; if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) { - stats_.packets_discarded_no_receiver_size.AddSample(packet_size.bytes()); + stats_.packets_discarded_no_receiver_size.AddSample( + {.value = packet_size.bytes<double>(), .time = clock_.CurrentTime()}); } } @@ -157,7 +162,9 @@ void EmulatedNetworkIncomingStatsBuilder::OnPacketReceived( stats_.ecn_count.Add(packet.ecn); stats_.bytes_received += DataSize::Bytes(packet.ip_packet_size()); if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) { - stats_.received_packets_size.AddSample(packet.ip_packet_size()); + stats_.received_packets_size.AddSample( + {.value = static_cast<double>(packet.ip_packet_size()), + .time = received_time}); } } @@ -188,15 +195,17 @@ EmulatedNetworkIncomingStats EmulatedNetworkIncomingStatsBuilder::Build() } EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode) - : stats_gathering_mode_(stats_gathering_mode) { + : clock_(clock), stats_gathering_mode_(stats_gathering_mode) { sequence_checker_.Detach(); } EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder( + Clock& clock, IPAddress local_ip, EmulatedNetworkStatsGatheringMode stats_gathering_mode) - : stats_gathering_mode_(stats_gathering_mode) { + : clock_(clock), stats_gathering_mode_(stats_gathering_mode) { local_addresses_.push_back(local_ip); sequence_checker_.Detach(); } @@ -206,7 +215,8 @@ void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time, RTC_DCHECK_RUN_ON(&sequence_checker_); if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) { sent_packets_queue_wait_time_us_.AddSample( - (sent_time - packet.arrival_time).us()); + {.value = (sent_time - packet.arrival_time).us<double>(), + .time = clock_.CurrentTime()}); } auto it = outgoing_stats_per_destination_.find(packet.to.ipaddr()); if (it == outgoing_stats_per_destination_.end()) { @@ -228,7 +238,7 @@ void EmulatedNetworkStatsBuilder::OnPacketDropped(IPAddress source_ip, incoming_stats_per_source_ .emplace(source_ip, std::make_unique<EmulatedNetworkIncomingStatsBuilder>( - stats_gathering_mode_)) + clock_, stats_gathering_mode_)) .first->second->OnPacketDropped(packet_size); } else { it->second->OnPacketDropped(packet_size); @@ -244,7 +254,7 @@ void EmulatedNetworkStatsBuilder::OnPacketReceived( incoming_stats_per_source_ .emplace(packet.from.ipaddr(), std::make_unique<EmulatedNetworkIncomingStatsBuilder>( - stats_gathering_mode_)) + clock_, stats_gathering_mode_)) .first->second->OnPacketReceived(received_time, packet); } else { it->second->OnPacketReceived(received_time, packet); @@ -284,7 +294,7 @@ void EmulatedNetworkStatsBuilder::AddEmulatedNetworkStats( incoming_stats_per_source_ .emplace(entry.first, std::make_unique<EmulatedNetworkIncomingStatsBuilder>( - stats_gathering_mode_)) + clock_, stats_gathering_mode_)) .first->second->AddIncomingStats(entry.second); } else { it->second->AddIncomingStats(entry.second); @@ -306,16 +316,17 @@ EmulatedNetworkStats EmulatedNetworkStatsBuilder::Build() const { .local_addresses = local_addresses_, .overall_outgoing_stats = GetOverallOutgoingStats(outgoing_stats, stats_gathering_mode_), - .overall_incoming_stats = - GetOverallIncomingStats(incoming_stats, stats_gathering_mode_), + .overall_incoming_stats = GetOverallIncomingStats(clock_, incoming_stats, + stats_gathering_mode_), .outgoing_stats_per_destination = std::move(outgoing_stats), .incoming_stats_per_source = std::move(incoming_stats), .sent_packets_queue_wait_time_us = sent_packets_queue_wait_time_us_}; } EmulatedNetworkNodeStatsBuilder::EmulatedNetworkNodeStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode) - : stats_gathering_mode_(stats_gathering_mode) { + : clock_(clock), stats_gathering_mode_(stats_gathering_mode) { sequence_checker_.Detach(); } @@ -324,9 +335,11 @@ void EmulatedNetworkNodeStatsBuilder::AddPacketTransportTime( size_t packet_size) { RTC_DCHECK_RUN_ON(&sequence_checker_); if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) { - stats_.packet_transport_time.AddSample(time.ms<double>()); - stats_.size_to_packet_transport_time.AddSample(packet_size / - time.ms<double>()); + stats_.packet_transport_time.AddSample( + {.value = time.ms<double>(), .time = clock_.CurrentTime()}); + stats_.size_to_packet_transport_time.AddSample( + {.value = packet_size / time.ms<double>(), + .time = clock_.CurrentTime()}); } } @@ -368,7 +381,7 @@ LinkEmulation::LinkEmulation( network_behavior_(std::move(network_behavior)), receiver_(receiver), fake_dtls_handshake_sizes_(fake_dtls_handshake_sizes), - stats_builder_(stats_gathering_mode) { + stats_builder_(*clock_, stats_gathering_mode) { task_queue_->PostTask([&]() { RTC_DCHECK_RUN_ON(task_queue_); network_behavior_->RegisterDeliveryTimeChangedCallback([&]() { @@ -603,7 +616,7 @@ EmulatedEndpointImpl::EmulatedEndpointImpl(const Options& options, task_queue_(task_queue), router_(task_queue_), next_port_(kFirstEphemeralPort), - stats_builder_(options_.ip, options_.stats_gathering_mode) { + stats_builder_(*clock_, options_.ip, options_.stats_gathering_mode) { constexpr int kIPv4NetworkPrefixLength = 24; constexpr int kIPv6NetworkPrefixLength = 64; @@ -808,9 +821,12 @@ EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress( } EndpointsContainer::EndpointsContainer( + Clock* clock, const std::vector<EmulatedEndpointImpl*>& endpoints, EmulatedNetworkStatsGatheringMode stats_gathering_mode) - : endpoints_(endpoints), stats_gathering_mode_(stats_gathering_mode) {} + : clock_(clock), + endpoints_(endpoints), + stats_gathering_mode_(stats_gathering_mode) {} bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const { for (auto* e : endpoints_) { @@ -837,7 +853,7 @@ std::vector<EmulatedEndpoint*> EndpointsContainer::GetEndpoints() const { } EmulatedNetworkStats EndpointsContainer::GetStats() const { - EmulatedNetworkStatsBuilder stats_builder(stats_gathering_mode_); + EmulatedNetworkStatsBuilder stats_builder(*clock_, stats_gathering_mode_); for (auto* endpoint : endpoints_) { stats_builder.AddEmulatedNetworkStats(endpoint->stats()); } diff --git a/third_party/libwebrtc/test/network/network_emulation.h b/third_party/libwebrtc/test/network/network_emulation.h @@ -72,6 +72,7 @@ class EmulatedNetworkOutgoingStatsBuilder { class EmulatedNetworkIncomingStatsBuilder { public: explicit EmulatedNetworkIncomingStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode); void OnPacketDropped(DataSize packet_size); @@ -85,6 +86,7 @@ class EmulatedNetworkIncomingStatsBuilder { EmulatedNetworkIncomingStats Build() const; private: + Clock& clock_; const EmulatedNetworkStatsGatheringMode stats_gathering_mode_; RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; @@ -96,8 +98,10 @@ class EmulatedNetworkIncomingStatsBuilder { class EmulatedNetworkStatsBuilder { public: explicit EmulatedNetworkStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode); explicit EmulatedNetworkStatsBuilder( + Clock& clock, IPAddress local_ip, EmulatedNetworkStatsGatheringMode stats_gathering_mode); @@ -113,6 +117,7 @@ class EmulatedNetworkStatsBuilder { EmulatedNetworkStats Build() const; private: + Clock& clock_; const EmulatedNetworkStatsGatheringMode stats_gathering_mode_; RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; @@ -129,6 +134,7 @@ class EmulatedNetworkStatsBuilder { class EmulatedNetworkNodeStatsBuilder { public: explicit EmulatedNetworkNodeStatsBuilder( + Clock& clock, EmulatedNetworkStatsGatheringMode stats_gathering_mode); void AddPacketTransportTime(TimeDelta time, size_t packet_size); @@ -138,6 +144,7 @@ class EmulatedNetworkNodeStatsBuilder { EmulatedNetworkNodeStats Build() const; private: + Clock& clock_; const EmulatedNetworkStatsGatheringMode stats_gathering_mode_; RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; @@ -379,7 +386,8 @@ class EmulatedRoute { // This object is immutable and so thread safe. class EndpointsContainer { public: - EndpointsContainer(const std::vector<EmulatedEndpointImpl*>& endpoints, + EndpointsContainer(Clock* clock, + const std::vector<EmulatedEndpointImpl*>& endpoints, EmulatedNetworkStatsGatheringMode stats_gathering_mode); EmulatedEndpointImpl* LookupByLocalAddress(const IPAddress& local_ip) const; @@ -391,6 +399,7 @@ class EndpointsContainer { EmulatedNetworkStats GetStats() const; private: + Clock* const clock_; const std::vector<EmulatedEndpointImpl*> endpoints_; const EmulatedNetworkStatsGatheringMode stats_gathering_mode_; }; diff --git a/third_party/libwebrtc/test/network/network_emulation_manager.cc b/third_party/libwebrtc/test/network/network_emulation_manager.cc @@ -310,7 +310,7 @@ NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface( endpoint_impls.push_back(static_cast<EmulatedEndpointImpl*>(endpoint)); } auto endpoints_container = std::make_unique<EndpointsContainer>( - endpoint_impls, stats_gathering_mode_); + clock_, endpoint_impls, stats_gathering_mode_); auto network_manager = std::make_unique<EmulatedNetworkManager>( time_controller_.get(), task_queue_.Get(), endpoints_container.get()); for (auto* endpoint : endpoints) { @@ -328,9 +328,9 @@ NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface( void NetworkEmulationManagerImpl::GetStats( ArrayView<EmulatedEndpoint* const> endpoints, std::function<void(EmulatedNetworkStats)> stats_callback) { - task_queue_.PostTask([endpoints, stats_callback, + task_queue_.PostTask([endpoints, stats_callback, clock = clock_, stats_gathering_mode = stats_gathering_mode_]() { - EmulatedNetworkStatsBuilder stats_builder(stats_gathering_mode); + EmulatedNetworkStatsBuilder stats_builder(*clock, stats_gathering_mode); for (auto* endpoint : endpoints) { // It's safe to cast here because EmulatedEndpointImpl can be the only // implementation of EmulatedEndpoint, because only it has access to @@ -345,14 +345,14 @@ void NetworkEmulationManagerImpl::GetStats( void NetworkEmulationManagerImpl::GetStats( ArrayView<EmulatedNetworkNode* const> nodes, std::function<void(EmulatedNetworkNodeStats)> stats_callback) { - task_queue_.PostTask( - [nodes, stats_callback, stats_gathering_mode = stats_gathering_mode_]() { - EmulatedNetworkNodeStatsBuilder stats_builder(stats_gathering_mode); - for (auto* node : nodes) { - stats_builder.AddEmulatedNetworkNodeStats(node->stats()); - } - stats_callback(stats_builder.Build()); - }); + task_queue_.PostTask([nodes, stats_callback, clock = clock_, + stats_gathering_mode = stats_gathering_mode_]() { + EmulatedNetworkNodeStatsBuilder stats_builder(*clock, stats_gathering_mode); + for (auto* node : nodes) { + stats_builder.AddEmulatedNetworkNodeStats(node->stats()); + } + stats_callback(stats_builder.Build()); + }); } std::optional<IPAddress> NetworkEmulationManagerImpl::GetNextIPv4Address() { diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc @@ -93,24 +93,28 @@ void DefaultAudioQualityAnalyzer::OnStatsReports( AudioStreamStats& audio_stream_stats = streams_stats_[stream_info.stream_label]; audio_stream_stats.expand_rate.AddSample( - (sample.concealed_samples - prev_sample.concealed_samples) / - total_samples_diff); + {.value = (sample.concealed_samples - prev_sample.concealed_samples) / + total_samples_diff, + .time = report->timestamp()}); audio_stream_stats.accelerate_rate.AddSample( - (sample.removed_samples_for_acceleration - - prev_sample.removed_samples_for_acceleration) / - total_samples_diff); + {.value = (sample.removed_samples_for_acceleration - + prev_sample.removed_samples_for_acceleration) / + total_samples_diff, + .time = report->timestamp()}); audio_stream_stats.preemptive_rate.AddSample( - (sample.inserted_samples_for_deceleration - - prev_sample.inserted_samples_for_deceleration) / - total_samples_diff); + {.value = (sample.inserted_samples_for_deceleration - + prev_sample.inserted_samples_for_deceleration) / + total_samples_diff, + .time = report->timestamp()}); int64_t speech_concealed_samples = sample.concealed_samples - sample.silent_concealed_samples; int64_t prev_speech_concealed_samples = prev_sample.concealed_samples - prev_sample.silent_concealed_samples; audio_stream_stats.speech_expand_rate.AddSample( - (speech_concealed_samples - prev_speech_concealed_samples) / - total_samples_diff); + {.value = (speech_concealed_samples - prev_speech_concealed_samples) / + total_samples_diff, + .time = report->timestamp()}); int64_t jitter_buffer_emitted_count_diff = sample.jitter_buffer_emitted_count - @@ -122,15 +126,20 @@ void DefaultAudioQualityAnalyzer::OnStatsReports( sample.jitter_buffer_target_delay - prev_sample.jitter_buffer_target_delay; audio_stream_stats.average_jitter_buffer_delay_ms.AddSample( - jitter_buffer_delay_diff.ms<double>() / - jitter_buffer_emitted_count_diff); + {.value = jitter_buffer_delay_diff.ms<double>() / + jitter_buffer_emitted_count_diff, + .time = report->timestamp()}); audio_stream_stats.preferred_buffer_size_ms.AddSample( - jitter_buffer_target_delay_diff.ms<double>() / - jitter_buffer_emitted_count_diff); + {.value = jitter_buffer_target_delay_diff.ms<double>() / + jitter_buffer_emitted_count_diff, + .time = report->timestamp()}); } - audio_stream_stats.energy.AddSample(sqrt( - (sample.total_audio_energy - prev_sample.total_audio_energy) / - (sample.total_samples_duration - prev_sample.total_samples_duration))); + audio_stream_stats.energy.AddSample( + {.value = + sqrt((sample.total_audio_energy - prev_sample.total_audio_energy) / + (sample.total_samples_duration - + prev_sample.total_samples_duration)), + .time = report->timestamp()}); last_stats_sample_[stream_info.stream_label] = sample; } diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/analyzing_video_sink.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/analyzing_video_sink.cc @@ -115,7 +115,8 @@ void AnalyzingVideoSink::OnFrame(const VideoFrame& frame) { if (report_infra_stats_) { stats_.analyzing_sink_processing_time_ms.AddSample( - (processing_finished - processing_started).ms<double>()); + {.value = (processing_finished - processing_started).ms<double>(), + .time = processing_finished}); } } } @@ -151,8 +152,9 @@ VideoFrame AnalyzingVideoSink::ScaleVideoFrame( !required_resolution.IsRegular() || (required_resolution.width() == 0 || required_resolution.height() == 0)) { if (report_infra_stats_) { + Timestamp now = clock_->CurrentTime(); stats_.scaling_tims_ms.AddSample( - (clock_->CurrentTime() - processing_started).ms<double>()); + {.value = (now - processing_started).ms<double>(), .time = now}); } return frame; } @@ -177,8 +179,9 @@ VideoFrame AnalyzingVideoSink::ScaleVideoFrame( VideoFrame scaled_frame = frame; scaled_frame.set_video_frame_buffer(scaled_buffer); if (report_infra_stats_) { + Timestamp now = clock_->CurrentTime(); stats_.scaling_tims_ms.AddSample( - (clock_->CurrentTime() - processing_started).ms<double>()); + {.value = (now - processing_started).ms<double>(), .time = now}); } return scaled_frame; } diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc @@ -132,12 +132,6 @@ std::optional<T> MaybeGetValue(const std::map<size_t, T>& map, size_t key) { return it->second; } -SamplesStatsCounter::StatsSample StatsSample(double value, - Timestamp sampling_time) { - return SamplesStatsCounter::StatsSample{.value = value, - .time = sampling_time}; -} - } // namespace DefaultVideoQualityAnalyzer::DefaultVideoQualityAnalyzer( @@ -253,7 +247,8 @@ uint16_t DefaultVideoQualityAnalyzer::OnFrameCaptured( stream_frame_counters_.at(key).dropped++; analyzer_stats_.frames_in_flight_left_count.AddSample( - StatsSample(captured_frames_in_flight_.size(), Now())); + {.value = static_cast<double>(captured_frames_in_flight_.size()), + .time = Now()}); frames_comparator_.AddComparison( InternalStatsKey(stream_index, peer_index, i), /*captured=*/std::nullopt, @@ -283,7 +278,7 @@ uint16_t DefaultVideoQualityAnalyzer::OnFrameCaptured( if (options_.report_infra_metrics) { analyzer_stats_.on_frame_captured_processing_time_ms.AddSample( - (Now() - captured_time).ms<double>()); + {.value = (Now() - captured_time).ms<double>(), .time = Now()}); } } return frame_id; @@ -316,7 +311,7 @@ void DefaultVideoQualityAnalyzer::OnFramePreEncode(absl::string_view peer_name, if (options_.report_infra_metrics) { analyzer_stats_.on_frame_pre_encode_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -386,7 +381,7 @@ void DefaultVideoQualityAnalyzer::OnFrameEncoded( if (options_.report_infra_metrics) { analyzer_stats_.on_frame_encoded_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -445,7 +440,7 @@ void DefaultVideoQualityAnalyzer::OnFramePreDecode( if (options_.report_infra_metrics) { analyzer_stats_.on_frame_pre_decode_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -491,7 +486,7 @@ void DefaultVideoQualityAnalyzer::OnFrameDecoded(absl::string_view peer_name, if (options_.report_infra_metrics) { analyzer_stats_.on_frame_decoded_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -580,7 +575,8 @@ void DefaultVideoQualityAnalyzer::OnFrameRendered(absl::string_view peer_name, state->SetLastRenderedFrameTime(peer_index, frame_in_flight->rendered_time(peer_index)); analyzer_stats_.frames_in_flight_left_count.AddSample( - StatsSample(captured_frames_in_flight_.size(), Now())); + {.value = static_cast<double>(captured_frames_in_flight_.size()), + .time = Now()}); frames_comparator_.AddComparison( stats_key, dropped_count, captured_frame, /*rendered=*/frame, FrameComparisonType::kRegular, @@ -593,7 +589,7 @@ void DefaultVideoQualityAnalyzer::OnFrameRendered(absl::string_view peer_name, if (options_.report_infra_metrics) { analyzer_stats_.on_frame_rendered_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -649,7 +645,7 @@ void DefaultVideoQualityAnalyzer::OnDecoderError(absl::string_view peer_name, if (options_.report_infra_metrics) { analyzer_stats_.on_decoder_error_processing_time_ms.AddSample( - (Now() - processing_started).ms<double>()); + {.value = (Now() - processing_started).ms<double>(), .time = Now()}); } } @@ -796,7 +792,8 @@ void DefaultVideoQualityAnalyzer::Stop() { // Add the amount of frames in flight to the analyzer stats before all left // frames in flight will be sent to the `frames_compartor_`. analyzer_stats_.frames_in_flight_left_count.AddSample( - StatsSample(captured_frames_in_flight_.size(), Now())); + {.value = static_cast<double>(captured_frames_in_flight_.size()), + .time = Now()}); for (auto& state_entry : stream_states_) { const size_t stream_index = state_entry.first; @@ -1064,7 +1061,8 @@ int DefaultVideoQualityAnalyzer::ProcessNotSeenFramesBeforeRendered( next_frame.MarkDropped(peer_index); analyzer_stats_.frames_in_flight_left_count.AddSample( - StatsSample(captured_frames_in_flight_.size(), Now())); + {.value = static_cast<double>(captured_frames_in_flight_.size()), + .time = Now()}); frames_comparator_.AddComparison(stats_key, /*captured=*/std::nullopt, /*rendered=*/std::nullopt, FrameComparisonType::kDroppedFrame, diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc @@ -247,7 +247,7 @@ void DefaultVideoQualityAnalyzerFramesComparator::Stop( // If there were no freezes on a video stream, add only one sample with // value 0 (0ms freezes time). if (stream_stats.freeze_time_ms.IsEmpty()) { - stream_stats.freeze_time_ms.AddSample(0); + stream_stats.freeze_time_ms.AddSample({.value = 0, .time = Now()}); } // Harmonic framerate (fps): diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc @@ -100,10 +100,12 @@ void VideoQualityMetricsReporter::OnStatsReports( MutexLock lock(&stats_lock_); VideoBweStats& video_bwe_stats = video_bwe_stats_[std::string(pc_label)]; if (ice_candidate_pair_stats.available_outgoing_bitrate.has_value()) { - video_bwe_stats.available_send_bandwidth.AddSample( - DataRate::BitsPerSec( - *ice_candidate_pair_stats.available_outgoing_bitrate) - .bytes_per_sec()); + video_bwe_stats.available_send_bandwidth.AddSample({ + .value = DataRate::BitsPerSec( + *ice_candidate_pair_stats.available_outgoing_bitrate) + .bytes_per_sec<double>(), + .time = clock_->CurrentTime(), + }); } StatsSample prev_sample = last_stats_sample_[std::string(pc_label)]; @@ -118,14 +120,18 @@ void VideoQualityMetricsReporter::OnStatsReports( DataRate retransmission_bitrate = (sample.retransmitted_bytes_sent - prev_sample.retransmitted_bytes_sent) / time_between_samples; - video_bwe_stats.retransmission_bitrate.AddSample( - retransmission_bitrate.bytes_per_sec()); + video_bwe_stats.retransmission_bitrate.AddSample({ + .value = retransmission_bitrate.bytes_per_sec<double>(), + .time = clock_->CurrentTime(), + }); DataRate transmission_bitrate = (sample.bytes_sent + sample.header_bytes_sent - prev_sample.bytes_sent - prev_sample.header_bytes_sent) / time_between_samples; - video_bwe_stats.transmission_bitrate.AddSample( - transmission_bitrate.bytes_per_sec()); + video_bwe_stats.transmission_bitrate.AddSample({ + .value = transmission_bitrate.bytes_per_sec<double>(), + .time = clock_->CurrentTime(), + }); } void VideoQualityMetricsReporter::StopAndReportResults() { diff --git a/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc @@ -98,12 +98,15 @@ void CrossMediaMetricsReporter::OnStatsReports( *video_stat->estimated_playout_timestamp; if (audio_video_playout_diff > 0) { stats_info_[sync_group].audio_ahead_ms.AddSample( - audio_video_playout_diff); - stats_info_[sync_group].video_ahead_ms.AddSample(0); + {.value = audio_video_playout_diff, .time = report->timestamp()}); + stats_info_[sync_group].video_ahead_ms.AddSample( + {.value = 0., .time = report->timestamp()}); } else { - stats_info_[sync_group].audio_ahead_ms.AddSample(0); + stats_info_[sync_group].audio_ahead_ms.AddSample( + {.value = 0., .time = report->timestamp()}); stats_info_[sync_group].video_ahead_ms.AddSample( - std::abs(audio_video_playout_diff)); + {.value = std::abs(audio_video_playout_diff), + .time = report->timestamp()}); } } } diff --git a/third_party/libwebrtc/test/peer_scenario/peer_scenario.h b/third_party/libwebrtc/test/peer_scenario/peer_scenario.h @@ -105,7 +105,7 @@ class PeerScenario { struct PeerVideoQualityPair { public: PeerVideoQualityPair(Clock* capture_clock, VideoQualityAnalyzer* analyzer) - : matcher_({analyzer->Handler()}), + : matcher_({analyzer->Handler(capture_clock)}), capture_tap_(capture_clock, &matcher_), decode_tap_(capture_clock, &matcher_, 0) {} VideoFrameMatcher matcher_; diff --git a/third_party/libwebrtc/test/scenario/performance_stats.cc b/third_party/libwebrtc/test/scenario/performance_stats.cc @@ -21,8 +21,11 @@ void VideoFramesStats::AddFrameInfo(const VideoFrameBuffer& frame, Timestamp at_time) { ++count; RTC_DCHECK(at_time.IsFinite()); - pixels.AddSample(frame.width() * frame.height()); - resolution.AddSample(std::max(frame.width(), frame.height())); + pixels.AddSample( + {.value = 1. * frame.width() * frame.height(), .time = at_time}); + resolution.AddSample( + {.value = static_cast<double>(std::max(frame.width(), frame.height())), + .time = at_time}); frames.AddEvent(at_time); } diff --git a/third_party/libwebrtc/test/scenario/scenario_unittest.cc b/third_party/libwebrtc/test/scenario/scenario_unittest.cc @@ -87,7 +87,8 @@ void SetupVideoCall(Scenario& s, VideoQualityAnalyzer* analyzer) { video.encoder.codec = VideoStreamConfig::Encoder::Codec::kVideoCodecVP8; video.encoder.implementation = VideoStreamConfig::Encoder::Implementation::kSoftware; - video.hooks.frame_pair_handlers = {analyzer->Handler()}; + video.hooks.frame_pair_handlers = { + analyzer->Handler(s.net()->time_controller()->GetClock())}; } s.CreateVideoStream(route->forward(), video); s.CreateAudioStream(route->forward(), AudioStreamConfig()); diff --git a/third_party/libwebrtc/test/scenario/stats_collection.cc b/third_party/libwebrtc/test/scenario/stats_collection.cc @@ -18,6 +18,7 @@ #include <vector> #include "api/rtc_event_log_output.h" +#include "api/units/data_rate.h" #include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" @@ -29,6 +30,7 @@ #include "rtc_base/checks.h" #include "rtc_base/memory_usage.h" #include "rtc_base/thread.h" +#include "system_wrappers/include/clock.h" #include "test/logging/log_writer.h" #include "test/scenario/performance_stats.h" @@ -52,26 +54,33 @@ void VideoQualityAnalyzer::PrintHeaders() { "render_height psnr\n"); } -std::function<void(const VideoFramePair&)> VideoQualityAnalyzer::Handler() { - return [this](VideoFramePair pair) { HandleFramePair(pair); }; +std::function<void(const VideoFramePair&)> VideoQualityAnalyzer::Handler( + Clock* clock) { + return [this, clock](VideoFramePair pair) { + HandleFramePair(pair, clock->CurrentTime()); + }; } -void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample, double psnr) { - layer_analyzers_[sample.layer_id].HandleFramePair(sample, psnr, - writer_.get()); +void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample, + double psnr, + Timestamp at_time) { + layer_analyzers_[sample.layer_id].HandleFramePair(sample, psnr, writer_.get(), + at_time); cached_.reset(); } -void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample) { +void VideoQualityAnalyzer::HandleFramePair(VideoFramePair sample, + Timestamp at_time) { double psnr = NAN; if (sample.decoded) psnr = I420PSNR(*sample.captured->ToI420(), *sample.decoded->ToI420()); if (config_.thread) { - config_.thread->PostTask( - [this, sample, psnr] { HandleFramePair(std::move(sample), psnr); }); + config_.thread->PostTask([this, sample, psnr, at_time] { + HandleFramePair(std::move(sample), psnr, at_time); + }); } else { - HandleFramePair(std::move(sample), psnr); + HandleFramePair(std::move(sample), psnr, at_time); } } @@ -93,7 +102,8 @@ VideoQualityStats& VideoQualityAnalyzer::stats() { void VideoLayerAnalyzer::HandleFramePair(VideoFramePair sample, double psnr, - RtcEventLogOutput* writer) { + RtcEventLogOutput* writer, + Timestamp at_time) { RTC_CHECK(sample.captured); HandleCapturedFrame(sample); if (!sample.decoded) { @@ -102,12 +112,12 @@ void VideoLayerAnalyzer::HandleFramePair(VideoFramePair sample, ++stats_.lost_count; ++skip_count_; } else { - stats_.psnr_with_freeze.AddSample(psnr); + stats_.psnr_with_freeze.AddSample({.value = psnr, .time = at_time}); if (sample.repeated) { ++stats_.freeze_count; ++skip_count_; } else { - stats_.psnr.AddSample(psnr); + stats_.psnr.AddSample({.value = psnr, .time = at_time}); HandleRenderedFrame(sample); } } @@ -128,11 +138,13 @@ void VideoLayerAnalyzer::HandleCapturedFrame(const VideoFramePair& sample) { } void VideoLayerAnalyzer::HandleRenderedFrame(const VideoFramePair& sample) { - stats_.capture_to_decoded_delay.AddSample(sample.decoded_time - - sample.capture_time); - stats_.end_to_end_delay.AddSample(sample.render_time - sample.capture_time); + stats_.capture_to_decoded_delay.AddSample( + sample.decoded_time - sample.capture_time, sample.capture_time); + stats_.end_to_end_delay.AddSample(sample.render_time - sample.capture_time, + sample.capture_time); stats_.render.AddFrameInfo(*sample.decoded, sample.render_time); - stats_.skipped_between_rendered.AddSample(skip_count_); + stats_.skipped_between_rendered.AddSample( + {.value = static_cast<double>(skip_count_), .time = sample.render_time}); skip_count_ = 0; if (last_render_time_.IsFinite()) { @@ -141,30 +153,37 @@ void VideoLayerAnalyzer::HandleRenderedFrame(const VideoFramePair& sample) { TimeDelta mean_interval = stats_.render.frames.interval().Mean(); if (render_interval > TimeDelta::Millis(150) + mean_interval || render_interval > 3 * mean_interval) { - stats_.freeze_duration.AddSample(render_interval); - stats_.time_between_freezes.AddSample(last_render_time_ - - last_freeze_time_); + stats_.freeze_duration.AddSample(render_interval, sample.capture_time); + stats_.time_between_freezes.AddSample( + last_render_time_ - last_freeze_time_, sample.capture_time); last_freeze_time_ = sample.render_time; } } last_render_time_ = sample.render_time; } -void CallStatsCollector::AddStats(Call::Stats sample) { +void CallStatsCollector::AddStats(Call::Stats sample, Timestamp at_time) { if (sample.send_bandwidth_bps > 0) - stats_.target_rate.AddSampleBps(sample.send_bandwidth_bps); + stats_.target_rate.AddSample( + DataRate::BitsPerSec(sample.send_bandwidth_bps), at_time); if (sample.pacer_delay_ms > 0) - stats_.pacer_delay.AddSample(TimeDelta::Millis(sample.pacer_delay_ms)); + stats_.pacer_delay.AddSample(TimeDelta::Millis(sample.pacer_delay_ms), + at_time); if (sample.rtt_ms > 0) - stats_.round_trip_time.AddSample(TimeDelta::Millis(sample.rtt_ms)); - stats_.memory_usage.AddSample(GetProcessResidentSizeBytes()); + stats_.round_trip_time.AddSample(TimeDelta::Millis(sample.rtt_ms), at_time); + stats_.memory_usage.AddSample( + {.value = static_cast<double>(GetProcessResidentSizeBytes()), + .time = at_time}); } void AudioReceiveStatsCollector::AddStats( - AudioReceiveStreamInterface::Stats sample) { - stats_.expand_rate.AddSample(sample.expand_rate); - stats_.accelerate_rate.AddSample(sample.accelerate_rate); - stats_.jitter_buffer.AddSampleMs(sample.jitter_buffer_ms); + AudioReceiveStreamInterface::Stats sample, + Timestamp at_time) { + stats_.expand_rate.AddSample({.value = sample.expand_rate, .time = at_time}); + stats_.accelerate_rate.AddSample( + {.value = sample.accelerate_rate, .time = at_time}); + stats_.jitter_buffer.AddSample(TimeDelta::Millis(sample.jitter_buffer_ms), + at_time); } void VideoSendStatsCollector::AddStats(VideoSendStream::Stats sample, @@ -174,10 +193,15 @@ void VideoSendStatsCollector::AddStats(VideoSendStream::Stats sample, if (sample.encode_frame_rate <= 0) return; - stats_.encode_frame_rate.AddSample(sample.encode_frame_rate); - stats_.encode_time.AddSampleMs(sample.avg_encode_time_ms); - stats_.encode_usage.AddSample(sample.encode_usage_percent / 100.0); - stats_.media_bitrate.AddSampleBps(sample.media_bitrate_bps); + stats_.encode_frame_rate.AddSample( + {.value = static_cast<double>(sample.encode_frame_rate), + .time = at_time}); + stats_.encode_time.AddSample(TimeDelta::Millis(sample.avg_encode_time_ms), + at_time); + stats_.encode_usage.AddSample( + {.value = sample.encode_usage_percent / 100.0, .time = at_time}); + stats_.media_bitrate.AddSample(DataRate::BitsPerSec(sample.media_bitrate_bps), + at_time); size_t fec_bytes = 0; for (const auto& kv : sample.substreams) { @@ -187,21 +211,26 @@ void VideoSendStatsCollector::AddStats(VideoSendStream::Stats sample, if (last_update_.IsFinite()) { auto fec_delta = DataSize::Bytes(fec_bytes - last_fec_bytes_); auto time_delta = at_time - last_update_; - stats_.fec_bitrate.AddSample(fec_delta / time_delta); + stats_.fec_bitrate.AddSample(fec_delta / time_delta, at_time); } last_fec_bytes_ = fec_bytes; last_update_ = at_time; } void VideoReceiveStatsCollector::AddStats( - VideoReceiveStreamInterface::Stats sample) { + VideoReceiveStreamInterface::Stats sample, + Timestamp at_time) { if (sample.decode_ms > 0) - stats_.decode_time.AddSampleMs(sample.decode_ms); + stats_.decode_time.AddSample(TimeDelta::Millis(sample.decode_ms), at_time); if (sample.max_decode_ms > 0) - stats_.decode_time_max.AddSampleMs(sample.max_decode_ms); + stats_.decode_time_max.AddSample(TimeDelta::Millis(sample.max_decode_ms), + at_time); if (sample.width > 0 && sample.height > 0) { - stats_.decode_pixels.AddSample(sample.width * sample.height); - stats_.resolution.AddSample(sample.height); + stats_.decode_pixels.AddSample( + {.value = static_cast<double>(sample.width * sample.height), + .time = at_time}); + stats_.resolution.AddSample( + {.value = static_cast<double>(sample.height), .time = at_time}); } } } // namespace test diff --git a/third_party/libwebrtc/test/scenario/stats_collection.h b/third_party/libwebrtc/test/scenario/stats_collection.h @@ -24,6 +24,7 @@ #include "call/video_receive_stream.h" #include "call/video_send_stream.h" #include "rtc_base/thread.h" +#include "system_wrappers/include/clock.h" #include "test/scenario/performance_stats.h" namespace webrtc { @@ -40,7 +41,8 @@ class VideoLayerAnalyzer { void HandleRenderedFrame(const VideoFramePair& sample); void HandleFramePair(VideoFramePair sample, double psnr, - RtcEventLogOutput* writer); + RtcEventLogOutput* writer, + Timestamp at_time); VideoQualityStats stats_; Timestamp last_capture_time_ = Timestamp::MinusInfinity(); Timestamp last_render_time_ = Timestamp::MinusInfinity(); @@ -54,15 +56,16 @@ class VideoQualityAnalyzer { VideoQualityAnalyzerConfig config = VideoQualityAnalyzerConfig(), std::unique_ptr<RtcEventLogOutput> writer = nullptr); ~VideoQualityAnalyzer(); - void HandleFramePair(VideoFramePair sample); + void HandleFramePair(VideoFramePair sample, Timestamp at_time); std::vector<VideoQualityStats> layer_stats() const; VideoQualityStats& stats(); void PrintHeaders(); void PrintFrameInfo(const VideoFramePair& sample); - std::function<void(const VideoFramePair&)> Handler(); + std::function<void(const VideoFramePair&)> Handler(Clock* clock); private: - void HandleFramePair(VideoFramePair sample, double psnr); + void HandleFramePair(VideoFramePair sample, double psnr, Timestamp at_time); + const VideoQualityAnalyzerConfig config_; std::map<int, VideoLayerAnalyzer> layer_analyzers_; const std::unique_ptr<RtcEventLogOutput> writer_; @@ -71,7 +74,7 @@ class VideoQualityAnalyzer { class CallStatsCollector { public: - void AddStats(Call::Stats sample); + void AddStats(Call::Stats sample, Timestamp at_time); CollectedCallStats& stats() { return stats_; } private: @@ -79,7 +82,7 @@ class CallStatsCollector { }; class AudioReceiveStatsCollector { public: - void AddStats(AudioReceiveStreamInterface::Stats sample); + void AddStats(AudioReceiveStreamInterface::Stats sample, Timestamp at_time); CollectedAudioReceiveStats& stats() { return stats_; } private: @@ -97,7 +100,7 @@ class VideoSendStatsCollector { }; class VideoReceiveStatsCollector { public: - void AddStats(VideoReceiveStreamInterface::Stats sample); + void AddStats(VideoReceiveStreamInterface::Stats sample, Timestamp at_time); CollectedVideoReceiveStats& stats() { return stats_; } private: diff --git a/third_party/libwebrtc/test/scenario/stats_collection_unittest.cc b/third_party/libwebrtc/test/scenario/stats_collection_unittest.cc @@ -30,7 +30,8 @@ void CreateAnalyzedStream(Scenario* s, config.encoder.codec = VideoStreamConfig::Encoder::Codec::kVideoCodecVP8; config.encoder.implementation = VideoStreamConfig::Encoder::Implementation::kSoftware; - config.hooks.frame_pair_handlers = {analyzer->Handler()}; + config.hooks.frame_pair_handlers = { + analyzer->Handler(s->net()->time_controller()->GetClock())}; auto* caller = s->CreateClient("caller", CallClientConfig()); auto* callee = s->CreateClient("callee", CallClientConfig()); auto route = @@ -39,7 +40,7 @@ void CreateAnalyzedStream(Scenario* s, VideoStreamPair* video = s->CreateVideoStream(route->forward(), config); auto* audio = s->CreateAudioStream(route->forward(), AudioStreamConfig()); s->Every(TimeDelta::Seconds(1), [=] { - collectors->call.AddStats(caller->GetStats()); + collectors->call.AddStats(caller->GetStats(), s->Now()); VideoSendStream::Stats send_stats; caller->SendTask([&]() { send_stats = video->send()->GetStats(); }); @@ -47,7 +48,7 @@ void CreateAnalyzedStream(Scenario* s, AudioReceiveStreamInterface::Stats receive_stats; caller->SendTask([&]() { receive_stats = audio->receive()->GetStats(); }); - collectors->audio_receive.AddStats(receive_stats); + collectors->audio_receive.AddStats(receive_stats, s->Now()); // Querying the video stats from within the expected runtime environment // (i.e. the TQ that belongs to the CallClient, not the Scenario TQ that @@ -57,7 +58,7 @@ void CreateAnalyzedStream(Scenario* s, callee->SendTask([&video_stream, &video_receive_stats]() { video_receive_stats = video_stream->GetStats(); }); - collectors->video_receive.AddStats(video_receive_stats); + collectors->video_receive.AddStats(video_receive_stats, s->Now()); }); } } // namespace diff --git a/third_party/libwebrtc/test/testsupport/perf_test_unittest.cc b/third_party/libwebrtc/test/testsupport/perf_test_unittest.cc @@ -14,6 +14,7 @@ #include <string> #include "api/numerics/samples_stats_counter.h" +#include "api/units/timestamp.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/testsupport/rtc_expect_death.h" @@ -141,12 +142,14 @@ TEST_F(PerfTest, TestGetPerfResultsHistogramsWithStatsCounter) { ClearPerfResults(); ::testing::internal::CaptureStdout(); + Timestamp time = Timestamp::Zero(); + SamplesStatsCounter counter; - counter.AddSample(1); - counter.AddSample(2); - counter.AddSample(3); - counter.AddSample(4); - counter.AddSample(5); + counter.AddSample({.value = 1, .time = time}); + counter.AddSample({.value = 2, .time = time}); + counter.AddSample({.value = 3, .time = time}); + counter.AddSample({.value = 4, .time = time}); + counter.AddSample({.value = 5, .time = time}); PrintResult("measurement", "_modifier", "story", counter, "ms", false); proto::HistogramSet histogram_set; diff --git a/third_party/libwebrtc/video/video_analyzer.cc b/third_party/libwebrtc/video/video_analyzer.cc @@ -30,6 +30,7 @@ #include "api/test/metrics/global_metrics_logger_and_exporter.h" #include "api/test/metrics/metric.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "api/video/video_codec_type.h" #include "api/video/video_frame.h" #include "api/video/video_sink_interface.h" @@ -502,28 +503,41 @@ void VideoAnalyzer::PollStats() { // 2) `lock_` is acquired after internal pacer lock in SendRtp() // 3) internal pacer lock is acquired by GetStats(). Call::Stats call_stats = call_->GetStats(); + Timestamp now = clock_->CurrentTime(); MutexLock lock(&comparison_lock_); - send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps); + send_bandwidth_bps_.AddSample( + {.value = static_cast<double>(call_stats.send_bandwidth_bps), + .time = now}); VideoSendStream::Stats send_stats = send_stream_->GetStats(); // It's not certain that we yet have estimates for any of these stats. // Check that they are positive before mixing them in. if (send_stats.encode_frame_rate > 0) - encode_frame_rate_.AddSample(send_stats.encode_frame_rate); + encode_frame_rate_.AddSample( + {.value = static_cast<double>(send_stats.encode_frame_rate), + .time = now}); if (send_stats.avg_encode_time_ms > 0) - encode_time_ms_.AddSample(send_stats.avg_encode_time_ms); + encode_time_ms_.AddSample( + {.value = static_cast<double>(send_stats.avg_encode_time_ms), + .time = now}); if (send_stats.encode_usage_percent > 0) - encode_usage_percent_.AddSample(send_stats.encode_usage_percent); + encode_usage_percent_.AddSample( + {.value = static_cast<double>(send_stats.encode_usage_percent), + .time = now}); if (send_stats.media_bitrate_bps > 0) - media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps); + media_bitrate_bps_.AddSample( + {.value = static_cast<double>(send_stats.media_bitrate_bps), + .time = now}); size_t fec_bytes = 0; for (const auto& kv : send_stats.substreams) { fec_bytes += kv.second.rtp_stats.fec.payload_bytes + kv.second.rtp_stats.fec.padding_bytes; } - fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8); + fec_bitrate_bps_.AddSample( + {.value = static_cast<double>((fec_bytes - last_fec_bytes_) * 8), + .time = now}); last_fec_bytes_ = fec_bytes; if (receive_stream_ != nullptr) { @@ -543,11 +557,16 @@ void VideoAnalyzer::PollStats() { mean_decode_time_ms_ = receive_stats.total_decode_time.ms<double>() / receive_stats.frames_decoded; if (receive_stats.decode_ms > 0) - decode_time_ms_.AddSample(receive_stats.decode_ms); + decode_time_ms_.AddSample( + {.value = static_cast<double>(receive_stats.decode_ms), .time = now}); if (receive_stats.max_decode_ms > 0) - decode_time_max_ms_.AddSample(receive_stats.max_decode_ms); + decode_time_max_ms_.AddSample( + {.value = static_cast<double>(receive_stats.max_decode_ms), + .time = now}); if (receive_stats.width > 0 && receive_stats.height > 0) { - pixels_.AddSample(receive_stats.width * receive_stats.height); + pixels_.AddSample({.value = static_cast<double>(receive_stats.width * + receive_stats.height), + .time = now}); } // `frames_decoded` and `frames_rendered` are used because they are more @@ -564,12 +583,18 @@ void VideoAnalyzer::PollStats() { if (audio_receive_stream_ != nullptr) { AudioReceiveStreamInterface::Stats receive_stats = audio_receive_stream_->GetStats(/*get_and_clear_legacy_stats=*/true); - audio_expand_rate_.AddSample(receive_stats.expand_rate); - audio_accelerate_rate_.AddSample(receive_stats.accelerate_rate); - audio_jitter_buffer_ms_.AddSample(receive_stats.jitter_buffer_ms); + audio_expand_rate_.AddSample( + {.value = receive_stats.expand_rate, .time = now}); + audio_accelerate_rate_.AddSample( + {.value = receive_stats.accelerate_rate, .time = now}); + audio_jitter_buffer_ms_.AddSample( + {.value = static_cast<double>(receive_stats.jitter_buffer_ms), + .time = now}); } - memory_usage_.AddSample(GetProcessResidentSizeBytes()); + memory_usage_.AddSample( + {.value = static_cast<double>(GetProcessResidentSizeBytes()), + .time = now}); } bool VideoAnalyzer::CompareFrames() { @@ -690,7 +715,9 @@ void VideoAnalyzer::PrintResults() { // Record the time from the last freeze until the last rendered frame to // ensure we cover the full timespan of the session. Otherwise the metric // would penalize an early freeze followed by no freezes until the end. - time_between_freezes_.AddSample(last_render_time_ - last_unfreeze_time_ms_); + time_between_freezes_.AddSample( + {.value = static_cast<double>(last_render_time_ - last_unfreeze_time_ms_), + .time = clock_->CurrentTime()}); // Freeze metrics. PrintResult("time_between_freezes", time_between_freezes_, @@ -797,6 +824,7 @@ void VideoAnalyzer::PrintResults() { void VideoAnalyzer::PerformFrameComparison( const VideoAnalyzer::FrameComparison& comparison) { // Perform expensive psnr and ssim calculations while not holding lock. + Timestamp now = clock_->CurrentTime(); double psnr = -1.0; double ssim = -1.0; if (comparison.reference && !comparison.dropped) { @@ -817,9 +845,9 @@ void VideoAnalyzer::PerformFrameComparison( comparison.encoded_frame_size, psnr, ssim)); } if (psnr >= 0.0) - psnr_.AddSample(psnr); + psnr_.AddSample({.value = psnr, .time = now}); if (ssim >= 0.0) - ssim_.AddSample(ssim); + ssim_.AddSample({.value = ssim, .time = now}); if (comparison.dropped) { ++dropped_frames_; @@ -830,18 +858,24 @@ void VideoAnalyzer::PerformFrameComparison( if (last_render_time_ != 0) { const int64_t render_delta_ms = comparison.render_time_ms - last_render_time_; - rendered_delta_.AddSample(render_delta_ms); + rendered_delta_.AddSample( + {.value = static_cast<double>(render_delta_ms), .time = now}); if (last_render_delta_ms_ != 0 && render_delta_ms - last_render_delta_ms_ > 150) { - time_between_freezes_.AddSample(last_render_time_ - - last_unfreeze_time_ms_); + time_between_freezes_.AddSample( + {.value = + static_cast<double>(last_render_time_ - last_unfreeze_time_ms_), + .time = now}); last_unfreeze_time_ms_ = comparison.render_time_ms; } last_render_delta_ms_ = render_delta_ms; } last_render_time_ = comparison.render_time_ms; - sender_time_.AddSample(comparison.send_time_ms - comparison.input_time_ms); + sender_time_.AddSample( + {.value = static_cast<double>(comparison.send_time_ms - + comparison.input_time_ms), + .time = now}); if (comparison.recv_time_ms > 0) { // If recv_time_ms == 0, this frame consisted of a packets which were all // lost in the transport. Since we were able to render the frame, however, @@ -855,12 +889,22 @@ void VideoAnalyzer::PerformFrameComparison( // strategies the timestamp of the received packets is set to the // timestamp of the protected/retransmitted media packet. I.e., then // recv_time_ms != 0, even though the media packets were lost. - receiver_time_.AddSample(comparison.render_time_ms - - comparison.recv_time_ms); - network_time_.AddSample(comparison.recv_time_ms - comparison.send_time_ms); + receiver_time_.AddSample( + {.value = static_cast<double>(comparison.render_time_ms - + comparison.recv_time_ms), + .time = now}); + network_time_.AddSample( + {.value = static_cast<double>(comparison.recv_time_ms - + comparison.send_time_ms), + .time = now}); } - end_to_end_.AddSample(comparison.render_time_ms - comparison.input_time_ms); - encoded_frame_size_.AddSample(comparison.encoded_frame_size); + end_to_end_.AddSample( + {.value = static_cast<double>(comparison.render_time_ms - + comparison.input_time_ms), + .time = now}); + encoded_frame_size_.AddSample( + {.value = static_cast<double>(comparison.encoded_frame_size), + .time = now}); } void VideoAnalyzer::PrintResult(absl::string_view result_type,