Add RtcEventBweUpdateScream to WebRTC event logs.
This change introduces a new event type, `BweUpdateScream`, to log parameters
related to the Scream bandwidth estimation algorithm. The event includes
fields such as reference window size, target rate, smoothed RTT, average
queue delay, and fraction of L4S marked packets.
Bug: webrtc:447037083
Change-Id: If776a4236f45c3dd284643d3427a9e0a707b615d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/417300
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45944}
diff --git a/api/rtc_event_log/rtc_event.h b/api/rtc_event_log/rtc_event.h
index 04015a6..e77cd8d 100644
--- a/api/rtc_event_log/rtc_event.h
+++ b/api/rtc_event_log/rtc_event.h
@@ -39,6 +39,7 @@
AudioSendStreamConfig,
BweUpdateDelayBased,
BweUpdateLossBased,
+ BweUpdateScream,
DtlsTransportState,
DtlsWritableState,
IceCandidatePairConfig,
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index 2912873..c386930 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -179,6 +179,26 @@
]
}
+rtc_library("rtc_event_bwe_update_scream") {
+ sources = [
+ "rtc_event_log/events/rtc_event_bwe_update_scream.cc",
+ "rtc_event_log/events/rtc_event_bwe_update_scream.h",
+ ]
+
+ deps = [
+ ":rtc_event_log_parse_status",
+ "../api:array_view",
+ "../api/rtc_event_log",
+ "../api/units:data_rate",
+ "../api/units:data_size",
+ "../api/units:time_delta",
+ "../api/units:timestamp",
+ "../rtc_base:checks",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings:string_view",
+ ]
+}
+
rtc_library("rtc_event_frame_events") {
visibility = [ "*" ]
sources = [
@@ -359,6 +379,7 @@
":rtc_event_audio",
":rtc_event_begin_end",
":rtc_event_bwe",
+ ":rtc_event_bwe_update_scream",
":rtc_event_field",
":rtc_event_frame_events",
":rtc_event_generic_packet_events",
@@ -507,6 +528,7 @@
":rtc_event_audio",
":rtc_event_begin_end",
":rtc_event_bwe",
+ ":rtc_event_bwe_update_scream",
":rtc_event_frame_events",
":rtc_event_generic_packet_events",
":rtc_event_log2_proto",
@@ -578,6 +600,7 @@
":rtc_event_audio",
":rtc_event_begin_end",
":rtc_event_bwe",
+ ":rtc_event_bwe_update_scream",
":rtc_event_field",
":rtc_event_frame_events",
":rtc_event_generic_packet_events",
@@ -611,6 +634,7 @@
"../api/rtc_event_log:rtc_event_log_factory",
"../api/transport:bandwidth_usage",
"../api/units:data_rate",
+ "../api/units:data_size",
"../api/units:time_delta",
"../api/units:timestamp",
"../api/video:video_frame",
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
index 3de0c62..f3d204e 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -295,6 +295,10 @@
return EncodeBweUpdateLossBased(rtc_event);
}
+ case RtcEvent::Type::BweUpdateScream: {
+ return "";
+ }
+
case RtcEvent::Type::DtlsTransportState: {
return "";
}
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
index 3ed905b..f7d70af 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
@@ -42,6 +42,7 @@
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
@@ -722,6 +723,7 @@
std::vector<const RtcEventAudioSendStreamConfig*> audio_send_stream_configs;
std::vector<const RtcEventBweUpdateDelayBased*> bwe_delay_based_updates;
std::vector<const RtcEventBweUpdateLossBased*> bwe_loss_based_updates;
+ std::vector<const RtcEventBweUpdateScream*> bwe_scream_updates;
std::vector<const RtcEventDtlsTransportState*> dtls_transport_states;
std::vector<const RtcEventDtlsWritableState*> dtls_writable_states;
std::map<uint32_t /* SSRC */, std::vector<const RtcEventFrameDecoded*>>
@@ -794,6 +796,12 @@
bwe_loss_based_updates.push_back(rtc_event);
break;
}
+ case RtcEvent::Type::BweUpdateScream: {
+ auto* rtc_event =
+ static_cast<const RtcEventBweUpdateScream* const>(it->get());
+ bwe_scream_updates.push_back(rtc_event);
+ break;
+ }
case RtcEvent::Type::DtlsTransportState: {
auto* rtc_event =
static_cast<const RtcEventDtlsTransportState* const>(it->get());
@@ -936,6 +944,7 @@
EncodeNetEqSetMinimumDelay(neteq_set_minimum_delay_events, &event_stream);
EncodeBweUpdateDelayBased(bwe_delay_based_updates, &event_stream);
EncodeBweUpdateLossBased(bwe_loss_based_updates, &event_stream);
+ EncodeBweUpdateScream(bwe_scream_updates, &event_stream);
EncodeDtlsTransportState(dtls_transport_states, &event_stream);
EncodeDtlsWritableState(dtls_writable_states, &event_stream);
for (const auto& kv : frames_decoded) {
@@ -1382,6 +1391,92 @@
}
}
+void RtcEventLogEncoderNewFormat::EncodeBweUpdateScream(
+ ArrayView<const RtcEventBweUpdateScream*> batch,
+ rtclog2::EventStream* event_stream) {
+ if (batch.empty())
+ return;
+
+ // Base event
+ const RtcEventBweUpdateScream* const base_event = batch[0];
+ rtclog2::ScreamBweUpdates* proto_batch =
+ event_stream->add_scream_bwe_updates();
+ proto_batch->set_timestamp_ms(base_event->timestamp_ms());
+ proto_batch->set_ref_window_bytes(base_event->ref_window_bytes());
+ proto_batch->set_target_rate_kbps(base_event->target_rate_kbps());
+ proto_batch->set_smoothed_rtt_ms(base_event->smoothed_rtt_ms());
+ proto_batch->set_avg_queue_delay_ms(base_event->avg_queue_delay_ms());
+ proto_batch->set_l4s_marked_permille(base_event->l4s_marked_permille());
+
+ if (batch.size() == 1)
+ return;
+
+ // Delta encoding
+ proto_batch->set_number_of_deltas(batch.size() - 1);
+ std::vector<std::optional<uint64_t>> values(batch.size() - 1);
+ std::string encoded_deltas;
+
+ // timestamp_ms
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = ToUnsigned(event->timestamp_ms());
+ }
+ encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_timestamp_ms_deltas(encoded_deltas);
+ }
+
+ // ref_window_bytes
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = event->ref_window_bytes();
+ }
+ encoded_deltas = EncodeDeltas(base_event->ref_window_bytes(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_ref_window_bytes_deltas(encoded_deltas);
+ }
+
+ // target_rate_kbps
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = event->target_rate_kbps();
+ }
+ encoded_deltas = EncodeDeltas(base_event->target_rate_kbps(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_target_rate_kbps_deltas(encoded_deltas);
+ }
+
+ // smoothed_rtt_ms
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = event->smoothed_rtt_ms();
+ }
+ encoded_deltas = EncodeDeltas(base_event->smoothed_rtt_ms(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_smoothed_rtt_ms_deltas(encoded_deltas);
+ }
+
+ // avg_queue_delay_ms
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = event->avg_queue_delay_ms();
+ }
+ encoded_deltas = EncodeDeltas(base_event->avg_queue_delay_ms(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_avg_queue_delay_ms_deltas(encoded_deltas);
+ }
+
+ // l4s_marked_permille
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventBweUpdateScream* event = batch[i + 1];
+ values[i] = event->l4s_marked_permille();
+ }
+ encoded_deltas = EncodeDeltas(base_event->l4s_marked_permille(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_l4s_marked_permille_deltas(encoded_deltas);
+ }
+}
+
void RtcEventLogEncoderNewFormat::EncodeDtlsTransportState(
ArrayView<const RtcEventDtlsTransportState*> batch,
rtclog2::EventStream* event_stream) {
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
index 8554cd0..0c49845 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
@@ -38,6 +38,7 @@
class RtcEventAudioSendStreamConfig;
class RtcEventBweUpdateDelayBased;
class RtcEventBweUpdateLossBased;
+class RtcEventBweUpdateScream;
class RtcEventDtlsTransportState;
class RtcEventDtlsWritableState;
class RtcEventLoggingStarted;
@@ -94,6 +95,8 @@
void EncodeBweUpdateLossBased(
ArrayView<const RtcEventBweUpdateLossBased*> batch,
rtclog2::EventStream* event_stream);
+ void EncodeBweUpdateScream(ArrayView<const RtcEventBweUpdateScream*> batch,
+ rtclog2::EventStream* event_stream);
void EncodeDtlsTransportState(
ArrayView<const RtcEventDtlsTransportState*> batch,
rtclog2::EventStream* event_stream);
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
index e4d9e34..e654884 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -40,6 +40,7 @@
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
@@ -618,6 +619,30 @@
}
}
+TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateScream) {
+ std::unique_ptr<RtcEventLogEncoder> encoder = CreateEncoder();
+ std::vector<std::unique_ptr<RtcEventBweUpdateScream>> events(event_count_);
+ for (size_t i = 0; i < event_count_; ++i) {
+ events[i] = (i == 0 || !force_repeated_fields_) ? gen_.NewBweUpdateScream()
+ : events[0]->Copy();
+ history_.push_back(events[i]->Copy());
+ }
+
+ encoded_ += encoder->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
+
+ const auto& bwe_scream_updates = parsed_log_.bwe_scream_updates();
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
+ ASSERT_EQ(bwe_scream_updates.size(), 0u);
+ return;
+ }
+
+ ASSERT_EQ(bwe_scream_updates.size(), event_count_);
+ for (size_t i = 0; i < event_count_; ++i) {
+ verifier_.VerifyLoggedBweScreamUpdate(*events[i], bwe_scream_updates[i]);
+ }
+}
+
TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_scream.cc b/logging/rtc_event_log/events/rtc_event_bwe_update_scream.cc
new file mode 100644
index 0000000..681fb74
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_scream.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2025 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
+
+#include <cstdint>
+#include <memory>
+
+#include "absl/memory/memory.h"
+#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
+
+namespace webrtc {
+
+RtcEventBweUpdateScream::RtcEventBweUpdateScream(DataSize ref_window,
+ DataRate target_rate,
+ TimeDelta smoothed_rtt,
+ TimeDelta avg_queue_delay,
+ uint32_t l4s_marked_permille)
+ : ref_window_bytes_(ref_window.bytes()),
+ target_rate_kbps_(target_rate.kbps()),
+ smoothed_rtt_ms_(smoothed_rtt.ms()),
+ avg_queue_delay_ms_(avg_queue_delay.ms()),
+ l4s_marked_permille_(l4s_marked_permille) {}
+
+RtcEventBweUpdateScream::~RtcEventBweUpdateScream() = default;
+
+std::unique_ptr<RtcEventBweUpdateScream> RtcEventBweUpdateScream::Copy() const {
+ return absl::WrapUnique(new RtcEventBweUpdateScream(*this));
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_scream.h b/logging/rtc_event_log/events/rtc_event_bwe_update_scream.h
new file mode 100644
index 0000000..73a66c3
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_scream.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2025 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BWE_UPDATE_SCREAM_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BWE_UPDATE_SCREAM_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_log_parse_status.h"
+
+namespace webrtc {
+
+struct LoggedBweScreamUpdate {
+ LoggedBweScreamUpdate() = default;
+ LoggedBweScreamUpdate(Timestamp timestamp,
+ uint32_t ref_window_bytes,
+ uint32_t target_rate_kbps,
+ uint32_t smoothed_rtt_ms,
+ uint32_t avg_queue_delay_ms,
+ uint32_t l4s_marked_permille)
+ : timestamp(timestamp),
+ ref_window(DataSize::Bytes(ref_window_bytes)),
+ target_rate(DataRate::KilobitsPerSec(target_rate_kbps)),
+ smoothed_rtt(TimeDelta::Millis(smoothed_rtt_ms)),
+ avg_queue_delay(TimeDelta::Millis(avg_queue_delay_ms)),
+ l4s_marked_permille(l4s_marked_permille) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ DataSize ref_window;
+ DataRate target_rate;
+ TimeDelta smoothed_rtt;
+ TimeDelta avg_queue_delay;
+ uint32_t l4s_marked_permille;
+};
+
+class RtcEventBweUpdateScream final : public RtcEvent {
+ public:
+ static constexpr Type kType = Type::BweUpdateScream;
+
+ RtcEventBweUpdateScream(DataSize ref_window,
+ DataRate target_rate,
+ TimeDelta smoothed_rtt,
+ TimeDelta avg_queue_delay,
+ uint32_t l4s_marked_permille);
+ ~RtcEventBweUpdateScream() override;
+
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
+
+ std::unique_ptr<RtcEventBweUpdateScream> Copy() const;
+
+ uint32_t ref_window_bytes() const { return ref_window_bytes_; }
+ uint32_t target_rate_kbps() const { return target_rate_kbps_; }
+ uint32_t smoothed_rtt_ms() const { return smoothed_rtt_ms_; }
+ uint32_t avg_queue_delay_ms() const { return avg_queue_delay_ms_; }
+ uint32_t l4s_marked_permille() const { return l4s_marked_permille_; }
+
+ static std::string Encode(ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweScreamUpdate>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
+ private:
+ RtcEventBweUpdateScream(const RtcEventBweUpdateScream&) = default;
+
+ const uint32_t ref_window_bytes_;
+ const uint32_t target_rate_kbps_;
+ const uint32_t smoothed_rtt_ms_;
+ const uint32_t avg_queue_delay_ms_;
+ const uint32_t l4s_marked_permille_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BWE_UPDATE_SCREAM_H_
diff --git a/logging/rtc_event_log/rtc_event_log2.proto b/logging/rtc_event_log/rtc_event_log2.proto
index dd1b693..ada2cc0 100644
--- a/logging/rtc_event_log/rtc_event_log2.proto
+++ b/logging/rtc_event_log/rtc_event_log2.proto
@@ -2,6 +2,7 @@
// WITHOUT PRIOR WARNING. THIS FILE SHOULD NOT BE USED IN PRODUCTION CODE.
syntax = "proto2";
+
option optimize_for = LITE_RUNTIME;
package webrtc.rtclog2;
@@ -41,6 +42,7 @@
repeated RouteChange route_changes = 32;
repeated RemoteEstimates remote_estimates = 33;
repeated NetEqSetMinimumDelay neteq_set_minimum_delay = 34;
+ repeated ScreamBweUpdates scream_bwe_updates = 35;
repeated AudioRecvStreamConfig audio_recv_stream_configs = 101;
repeated AudioSendStreamConfig audio_send_stream_configs = 102;
@@ -444,6 +446,28 @@
optional bytes detector_state_deltas = 103;
}
+message ScreamBweUpdates {
+ // required
+ optional int64 timestamp_ms = 1;
+
+ optional uint32 ref_window_bytes = 2;
+ optional uint32 target_rate_kbps = 3;
+ optional uint32 smoothed_rtt_ms = 4;
+ optional uint32 avg_queue_delay_ms = 5;
+ optional uint32 l4s_marked_permille = 6;
+
+ // optional - required if the batch contains delta encoded events.
+ optional uint32 number_of_deltas = 7;
+
+ // Delta encodings.
+ optional bytes timestamp_ms_deltas = 101;
+ optional bytes ref_window_bytes_deltas = 102;
+ optional bytes target_rate_kbps_deltas = 103;
+ optional bytes smoothed_rtt_ms_deltas = 104;
+ optional bytes avg_queue_delay_ms_deltas = 105;
+ optional bytes l4s_marked_permille_deltas = 106;
+}
+
// Maps RTP header extension names to numerical IDs.
message RtpHeaderExtensionConfig {
// Optional IDs for the header extensions. Each ID is a 4-bit number that is
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index baac68a..762098e 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -1201,6 +1201,7 @@
bwe_probe_success_events_.clear();
bwe_delay_updates_.clear();
bwe_loss_updates_.clear();
+ bwe_scream_updates_.clear();
dtls_transport_states_.clear();
dtls_writable_states_.clear();
decoded_frames_.clear();
@@ -1354,6 +1355,7 @@
StoreFirstAndLastTimestamp(bwe_probe_success_events());
StoreFirstAndLastTimestamp(bwe_delay_updates());
StoreFirstAndLastTimestamp(bwe_loss_updates());
+ StoreFirstAndLastTimestamp(bwe_scream_updates());
for (const auto& frame_stream : decoded_frames()) {
StoreFirstAndLastTimestamp(frame_stream.second);
}
@@ -2716,6 +2718,7 @@
stream.audio_playout_events_size() + stream.begin_log_events_size() +
stream.end_log_events_size() + stream.loss_based_bwe_updates_size() +
stream.delay_based_bwe_updates_size() +
+ stream.scream_bwe_updates_size() +
stream.dtls_transport_state_events_size() +
stream.dtls_writable_states_size() +
stream.audio_network_adaptations_size() +
@@ -2753,6 +2756,8 @@
return StoreBweLossBasedUpdate(stream.loss_based_bwe_updates(0));
} else if (stream.delay_based_bwe_updates_size() == 1) {
return StoreBweDelayBasedUpdate(stream.delay_based_bwe_updates(0));
+ } else if (stream.scream_bwe_updates_size() == 1) {
+ return StoreBweScreamUpdate(stream.scream_bwe_updates(0));
} else if (stream.dtls_transport_state_events_size() == 1) {
return StoreDtlsTransportState(stream.dtls_transport_state_events(0));
} else if (stream.dtls_writable_states_size() == 1) {
@@ -3169,6 +3174,111 @@
return ParseStatus::Success();
}
+ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweScreamUpdate(
+ const rtclog2::ScreamBweUpdates& proto) {
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_ref_window_bytes());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_target_rate_kbps());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_smoothed_rtt_ms());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_avg_queue_delay_ms());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_l4s_marked_permille());
+
+ // Base event
+ bwe_scream_updates_.emplace_back(
+ Timestamp::Millis(proto.timestamp_ms()), proto.ref_window_bytes(),
+ proto.target_rate_kbps(), proto.smoothed_rtt_ms(),
+ proto.avg_queue_delay_ms(), proto.l4s_marked_permille());
+
+ const size_t number_of_deltas =
+ proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
+ if (number_of_deltas == 0) {
+ return ParseStatus::Success();
+ }
+
+ // timestamp_ms
+ std::vector<std::optional<uint64_t>> timestamp_ms_values =
+ DecodeDeltas(proto.timestamp_ms_deltas(),
+ ToUnsigned(proto.timestamp_ms()), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
+
+ // ref_window_bytes
+ std::vector<std::optional<uint64_t>> ref_window_bytes_values =
+ DecodeDeltas(proto.ref_window_bytes_deltas(), proto.ref_window_bytes(),
+ number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(ref_window_bytes_values.size(),
+ number_of_deltas);
+
+ // target_rate_kbps
+ std::vector<std::optional<uint64_t>> target_rate_kbps_values =
+ DecodeDeltas(proto.target_rate_kbps_deltas(), proto.target_rate_kbps(),
+ number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(target_rate_kbps_values.size(),
+ number_of_deltas);
+
+ // smoothed_rtt_ms
+ std::vector<std::optional<uint64_t>> smoothed_rtt_ms_values =
+ DecodeDeltas(proto.smoothed_rtt_ms_deltas(), proto.smoothed_rtt_ms(),
+ number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(smoothed_rtt_ms_values.size(), number_of_deltas);
+
+ // avg_queue_delay_ms
+ std::vector<std::optional<uint64_t>> avg_queue_delay_ms_values =
+ DecodeDeltas(proto.avg_queue_delay_ms_deltas(),
+ proto.avg_queue_delay_ms(), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(avg_queue_delay_ms_values.size(),
+ number_of_deltas);
+
+ // l4s_marked_permille
+ std::vector<std::optional<uint64_t>> l4s_marked_permille_values =
+ DecodeDeltas(proto.l4s_marked_permille_deltas(),
+ proto.l4s_marked_permille(), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(l4s_marked_permille_values.size(),
+ number_of_deltas);
+
+ // Populate events from decoded deltas
+ for (size_t i = 0; i < number_of_deltas; ++i) {
+ RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
+ int64_t timestamp_ms;
+ RTC_PARSE_CHECK_OR_RETURN(
+ ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
+
+ RTC_PARSE_CHECK_OR_RETURN(ref_window_bytes_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(ref_window_bytes_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ const uint32_t ref_window_bytes =
+ static_cast<uint32_t>(ref_window_bytes_values[i].value());
+
+ RTC_PARSE_CHECK_OR_RETURN(target_rate_kbps_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(target_rate_kbps_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ const uint32_t target_rate_kbps =
+ static_cast<uint32_t>(target_rate_kbps_values[i].value());
+
+ RTC_PARSE_CHECK_OR_RETURN(smoothed_rtt_ms_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(smoothed_rtt_ms_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ const uint32_t smoothed_rtt_ms =
+ static_cast<uint32_t>(smoothed_rtt_ms_values[i].value());
+
+ RTC_PARSE_CHECK_OR_RETURN(avg_queue_delay_ms_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(avg_queue_delay_ms_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ const uint32_t avg_queue_delay_ms =
+ static_cast<uint32_t>(avg_queue_delay_ms_values[i].value());
+
+ RTC_PARSE_CHECK_OR_RETURN(l4s_marked_permille_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(l4s_marked_permille_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ const uint32_t l4s_marked_permille =
+ static_cast<uint32_t>(l4s_marked_permille_values[i].value());
+
+ bwe_scream_updates_.emplace_back(
+ Timestamp::Millis(timestamp_ms), ref_window_bytes, target_rate_kbps,
+ smoothed_rtt_ms, avg_queue_delay_ms, l4s_marked_permille);
+ }
+ return ParseStatus::Success();
+}
+
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeClusterCreated(
const rtclog2::BweProbeCluster& proto) {
LoggedBweProbeClusterCreatedEvent probe_cluster;
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index 21cd333..9ecf121 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -36,6 +36,7 @@
#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_end_log.h"
@@ -497,6 +498,10 @@
return bwe_loss_updates_;
}
+ const std::vector<LoggedBweScreamUpdate>& bwe_scream_updates() const {
+ return bwe_scream_updates_;
+ }
+
// DTLS
const std::vector<LoggedDtlsTransportState>& dtls_transport_states() const {
return dtls_transport_states_;
@@ -761,6 +766,7 @@
const rtclog2::DelayBasedBweUpdates& proto);
ParseStatus StoreBweLossBasedUpdate(
const rtclog2::LossBasedBweUpdates& proto);
+ ParseStatus StoreBweScreamUpdate(const rtclog2::ScreamBweUpdates& proto);
ParseStatus StoreBweProbeClusterCreated(
const rtclog2::BweProbeCluster& proto);
ParseStatus StoreBweProbeFailureEvent(
@@ -898,6 +904,7 @@
std::vector<LoggedBweDelayBasedUpdate> bwe_delay_updates_;
std::vector<LoggedBweLossBasedUpdate> bwe_loss_updates_;
+ std::vector<LoggedBweScreamUpdate> bwe_scream_updates_;
std::vector<LoggedDtlsTransportState> dtls_transport_states_;
std::vector<LoggedDtlsWritableState> dtls_writable_states_;
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index 6a78d79..4e589cf 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -33,6 +33,7 @@
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
@@ -81,6 +82,7 @@
size_t ana_configs = 0;
size_t bwe_loss_events = 0;
size_t bwe_delay_events = 0;
+ size_t bwe_scream_events = 0;
size_t dtls_transport_states = 0;
size_t dtls_writable_states = 0;
size_t frame_decoded_events = 0;
@@ -98,12 +100,12 @@
size_t total_nonconfig_events() const {
return alr_states + route_changes + audio_playouts + ana_configs +
- bwe_loss_events + bwe_delay_events + dtls_transport_states +
- dtls_writable_states + frame_decoded_events + probe_creations +
- probe_successes + probe_failures + ice_configs + ice_events +
- incoming_rtp_packets + outgoing_rtp_packets + incoming_rtcp_packets +
- outgoing_rtcp_packets + generic_packets_sent +
- generic_packets_received;
+ bwe_loss_events + bwe_delay_events + bwe_scream_events +
+ dtls_transport_states + dtls_writable_states + frame_decoded_events +
+ probe_creations + probe_successes + probe_failures + ice_configs +
+ ice_events + incoming_rtp_packets + outgoing_rtp_packets +
+ incoming_rtcp_packets + outgoing_rtcp_packets +
+ generic_packets_sent + generic_packets_received;
}
size_t total_config_events() const {
@@ -189,6 +191,7 @@
ana_configs_list_;
std::vector<std::unique_ptr<RtcEventBweUpdateDelayBased>> bwe_delay_list_;
std::vector<std::unique_ptr<RtcEventBweUpdateLossBased>> bwe_loss_list_;
+ std::vector<std::unique_ptr<RtcEventBweUpdateScream>> bwe_scream_list_;
std::vector<std::unique_ptr<RtcEventDtlsTransportState>>
dtls_transport_state_list_;
std::vector<std::unique_ptr<RtcEventDtlsWritableState>>
@@ -449,6 +452,15 @@
}
selection -= count.bwe_delay_events;
+ if (selection < count.bwe_scream_events) {
+ auto event = gen_.NewBweUpdateScream();
+ event_log->Log(event->Copy());
+ bwe_scream_list_.push_back(std::move(event));
+ count.bwe_scream_events--;
+ continue;
+ }
+ selection -= count.bwe_scream_events;
+
if (selection < count.probe_creations) {
auto event = gen_.NewProbeClusterCreated();
event_log->Log(event->Copy());
@@ -661,6 +673,13 @@
parsed_bwe_loss_updates[i]);
}
+ auto& parsed_bwe_scream_updates = parsed_log.bwe_scream_updates();
+ ASSERT_EQ(parsed_bwe_scream_updates.size(), bwe_scream_list_.size());
+ for (size_t i = 0; i < parsed_bwe_scream_updates.size(); i++) {
+ verifier_.VerifyLoggedBweScreamUpdate(*bwe_scream_list_[i],
+ parsed_bwe_scream_updates[i]);
+ }
+
auto& parsed_bwe_probe_cluster_created_events =
parsed_log.bwe_probe_cluster_created_events();
ASSERT_EQ(parsed_bwe_probe_cluster_created_events.size(),
@@ -851,6 +870,7 @@
count.generic_packets_sent = 100;
count.generic_packets_received = 100;
count.route_changes = 4;
+ count.bwe_scream_events = 20;
}
WriteLog(count, 0);
@@ -884,6 +904,7 @@
count.generic_packets_sent = 500;
count.generic_packets_received = 500;
count.route_changes = 10;
+ count.bwe_scream_events = 50;
}
WriteLog(count, 500);
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index 1608651..3872f29 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -30,6 +30,7 @@
#include "api/rtp_parameters.h"
#include "api/transport/bandwidth_usage.h"
#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "api/video/video_codec_type.h"
@@ -42,6 +43,7 @@
#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_end_log.h"
@@ -201,6 +203,19 @@
bitrate_bps, fraction_lost, total_packets);
}
+std::unique_ptr<RtcEventBweUpdateScream> EventGenerator::NewBweUpdateScream() {
+ uint32_t ref_window_bytes = prng_.Rand(0u, 100000u);
+ uint32_t target_rate_kbps = prng_.Rand(0u, 40000u);
+ uint32_t smoothed_rtt_ms = prng_.Rand(0u, 10000u);
+ uint32_t avg_queue_delay_ms = prng_.Rand(0u, 5000u);
+ uint32_t l4s_marked_permille = prng_.Rand(0u, 1000u);
+ return std::make_unique<RtcEventBweUpdateScream>(
+ DataSize::Bytes(ref_window_bytes),
+ DataRate::KilobitsPerSec(target_rate_kbps),
+ TimeDelta::Millis(smoothed_rtt_ms), TimeDelta::Millis(avg_queue_delay_ms),
+ l4s_marked_permille);
+}
+
std::unique_ptr<RtcEventDtlsTransportState>
EventGenerator::NewDtlsTransportState() {
DtlsTransportState state = static_cast<DtlsTransportState>(
@@ -938,6 +953,19 @@
EXPECT_EQ(original_event.total_packets(), logged_event.expected_packets);
}
+void EventVerifier::VerifyLoggedBweScreamUpdate(
+ const RtcEventBweUpdateScream& original_event,
+ const LoggedBweScreamUpdate& logged_event) const {
+ EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
+ EXPECT_EQ(original_event.ref_window_bytes(), logged_event.ref_window.bytes());
+ EXPECT_EQ(original_event.target_rate_kbps(), logged_event.target_rate.kbps());
+ EXPECT_EQ(original_event.smoothed_rtt_ms(), logged_event.smoothed_rtt.ms());
+ EXPECT_EQ(original_event.avg_queue_delay_ms(),
+ logged_event.avg_queue_delay.ms());
+ EXPECT_EQ(original_event.l4s_marked_permille(),
+ logged_event.l4s_marked_permille);
+}
+
void EventVerifier::VerifyLoggedBweProbeClusterCreatedEvent(
const RtcEventProbeClusterCreated& original_event,
const LoggedBweProbeClusterCreatedEvent& logged_event) const {
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index b978af6..9da32b1 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -27,6 +27,7 @@
#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_end_log.h"
@@ -76,6 +77,7 @@
std::unique_ptr<RtcEventAudioPlayout> NewAudioPlayout(uint32_t ssrc);
std::unique_ptr<RtcEventBweUpdateDelayBased> NewBweUpdateDelayBased();
std::unique_ptr<RtcEventBweUpdateLossBased> NewBweUpdateLossBased();
+ std::unique_ptr<RtcEventBweUpdateScream> NewBweUpdateScream();
std::unique_ptr<RtcEventDtlsTransportState> NewDtlsTransportState();
std::unique_ptr<RtcEventDtlsWritableState> NewDtlsWritableState();
std::unique_ptr<RtcEventFrameDecoded> NewFrameDecodedEvent(uint32_t ssrc);
@@ -186,6 +188,10 @@
const RtcEventBweUpdateLossBased& original_event,
const LoggedBweLossBasedUpdate& logged_event) const;
+ void VerifyLoggedBweScreamUpdate(
+ const RtcEventBweUpdateScream& original_event,
+ const LoggedBweScreamUpdate& logged_event) const;
+
void VerifyLoggedBweProbeClusterCreatedEvent(
const RtcEventProbeClusterCreated& original_event,
const LoggedBweProbeClusterCreatedEvent& logged_event) const;
diff --git a/logging/rtc_event_log/rtc_event_processor_order.h b/logging/rtc_event_log/rtc_event_processor_order.h
index d4d1983..28b83f0 100644
--- a/logging/rtc_event_log/rtc_event_processor_order.h
+++ b/logging/rtc_event_log/rtc_event_processor_order.h
@@ -24,6 +24,7 @@
#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_scream.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_end_log.h"
@@ -76,6 +77,7 @@
BweDelayBased,
BweLossBased,
BweProbeCreated,
+ BweScream,
// General processing events. No obvious order.
AudioNetworkAdaptation,
NetEqSetMinDelay,
@@ -275,6 +277,16 @@
};
template <>
+class TieBreaker<LoggedBweScreamUpdate> {
+ public:
+ static constexpr int type_order = static_cast<int>(TypeOrder::BweScream);
+ static std::optional<uint16_t> transport_seq_num_accessor(
+ const LoggedBweScreamUpdate&) {
+ return std::optional<uint16_t>();
+ }
+};
+
+template <>
class TieBreaker<LoggedAudioNetworkAdaptationEvent> {
public:
static constexpr int type_order =