From d12a14e21f46bb6b34f8a14de57a3b6fc75a63cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Terelius?= Date: Tue, 8 Feb 2022 18:20:18 +0100 Subject: [PATCH] Add new RTC event log encoding for AudioPlayout and DelayBasedBwe events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:11933 Change-Id: Ia54d973099916c8dba9fedf362f25e46fe5cc541 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/246204 Reviewed-by: Sebastian Jansson Commit-Queue: Björn Terelius Cr-Commit-Position: refs/heads/main@{#35959} --- logging/BUILD.gn | 13 +- .../encoder/rtc_event_log_encoder_v3.cc | 3 + .../events/rtc_event_alr_state.h | 1 + .../events/rtc_event_audio_playout.cc | 5 + .../events/rtc_event_audio_playout.h | 30 ++++ .../events/rtc_event_begin_log.cc | 12 +- .../rtc_event_bwe_update_delay_based.cc | 6 + .../events/rtc_event_bwe_update_delay_based.h | 69 +++++++++ .../events/rtc_event_definition.h | 13 +- .../rtc_event_log/events/rtc_event_end_log.cc | 6 +- .../events/rtc_event_field_encoding.h | 82 ++++++++++ .../events/rtc_event_field_encoding_parser.h | 105 +++++++++++++ .../events/rtc_event_field_extraction.h | 146 ++---------------- logging/rtc_event_log/rtc_event_log_parser.cc | 9 +- 14 files changed, 350 insertions(+), 150 deletions(-) diff --git a/logging/BUILD.gn b/logging/BUILD.gn index ce40528dd3..f2385bee25 100644 --- a/logging/BUILD.gn +++ b/logging/BUILD.gn @@ -85,7 +85,10 @@ rtc_library("rtc_event_pacing") { "../api/rtc_event_log", "../api/units:timestamp", ] - absl_deps = [ "//third_party/abseil-cpp/absl/memory" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + ] } rtc_library("rtc_event_audio") { @@ -101,13 +104,17 @@ rtc_library("rtc_event_audio") { ] deps = [ + ":rtc_event_field", ":rtc_stream_config", "../api/rtc_event_log", "../api/units:timestamp", "../modules/audio_coding:audio_network_adaptor_config", "../rtc_base:checks", ] - absl_deps = [ "//third_party/abseil-cpp/absl/memory" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + ] } rtc_library("rtc_event_begin_end") { @@ -144,6 +151,7 @@ rtc_library("rtc_event_bwe") { ] deps = [ + ":rtc_event_field", "../api:network_state_predictor_api", "../api/rtc_event_log", "../api/units:data_rate", @@ -151,6 +159,7 @@ rtc_library("rtc_event_bwe") { ] absl_deps = [ "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] } diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc index 1fd5fa60bb..73d864464e 100644 --- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc +++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc @@ -75,6 +75,9 @@ std::string RtcEventLogEncoderV3::EncodeLogEnd(int64_t timestamp_us) { RtcEventLogEncoderV3::RtcEventLogEncoderV3() { encoders_[RtcEvent::Type::AlrStateEvent] = RtcEventAlrState::Encode; + encoders_[RtcEvent::Type::AudioPlayout] = RtcEventAudioPlayout::Encode; + encoders_[RtcEvent::Type::BweUpdateDelayBased] = + RtcEventBweUpdateDelayBased::Encode; } std::string RtcEventLogEncoderV3::EncodeBatch( diff --git a/logging/rtc_event_log/events/rtc_event_alr_state.h b/logging/rtc_event_log/events/rtc_event_alr_state.h index 2bc74089e0..44e68a680e 100644 --- a/logging/rtc_event_log/events/rtc_event_alr_state.h +++ b/logging/rtc_event_log/events/rtc_event_alr_state.h @@ -15,6 +15,7 @@ #include #include +#include "absl/strings/string_view.h" #include "api/rtc_event_log/rtc_event.h" #include "api/units/timestamp.h" #include "logging/rtc_event_log/events/rtc_event_definition.h" diff --git a/logging/rtc_event_log/events/rtc_event_audio_playout.cc b/logging/rtc_event_log/events/rtc_event_audio_playout.cc index dae61c4df3..21a3f9266c 100644 --- a/logging/rtc_event_log/events/rtc_event_audio_playout.cc +++ b/logging/rtc_event_log/events/rtc_event_audio_playout.cc @@ -14,6 +14,11 @@ namespace webrtc { +constexpr RtcEventDefinition + RtcEventAudioPlayout::definition_; + RtcEventAudioPlayout::RtcEventAudioPlayout(uint32_t ssrc) : ssrc_(ssrc) {} RtcEventAudioPlayout::RtcEventAudioPlayout(const RtcEventAudioPlayout& other) diff --git a/logging/rtc_event_log/events/rtc_event_audio_playout.h b/logging/rtc_event_log/events/rtc_event_audio_playout.h index e3f33e4784..2d9a24e1b7 100644 --- a/logging/rtc_event_log/events/rtc_event_audio_playout.h +++ b/logging/rtc_event_log/events/rtc_event_audio_playout.h @@ -13,10 +13,15 @@ #include +#include #include +#include +#include +#include "absl/strings/string_view.h" #include "api/rtc_event_log/rtc_event.h" #include "api/units/timestamp.h" +#include "logging/rtc_event_log/events/rtc_event_definition.h" namespace webrtc { @@ -46,10 +51,35 @@ class RtcEventAudioPlayout final : public RtcEvent { uint32_t ssrc() const { return ssrc_; } + static std::string Encode(rtc::ArrayView batch) { + return RtcEventAudioPlayout::definition_.EncodeBatch(batch); + } + + static RtcEventLogParseStatus Parse( + absl::string_view s, + bool batched, + std::map>& output) { + std::vector temp_output; + auto status = + RtcEventAudioPlayout::definition_.ParseBatch(s, batched, temp_output); + for (const LoggedAudioPlayoutEvent& event : temp_output) { + output[event.ssrc].push_back(event); + } + return status; + } + private: RtcEventAudioPlayout(const RtcEventAudioPlayout& other); const uint32_t ssrc_; + + static constexpr RtcEventDefinition + definition_{{"AudioPlayout", RtcEventAudioPlayout::kType}, + {&RtcEventAudioPlayout::ssrc_, + &LoggedAudioPlayoutEvent::ssrc, + {"ssrc", /*id=*/1, FieldType::kFixed32, /*width=*/32}}}; }; } // namespace webrtc diff --git a/logging/rtc_event_log/events/rtc_event_begin_log.cc b/logging/rtc_event_log/events/rtc_event_begin_log.cc index 15db8f5260..49b9effa9e 100644 --- a/logging/rtc_event_log/events/rtc_event_begin_log.cc +++ b/logging/rtc_event_log/events/rtc_event_begin_log.cc @@ -54,14 +54,18 @@ RtcEventLogParseStatus RtcEventBeginLog::Parse( parser.ParseNumericField(timestamp_params); if (!result.ok()) return result.status(); - PopulateRtcEventTimestamp(result.value(), &LoggedStartEvent::timestamp, - output_batch); + status = PopulateRtcEventTimestamp( + result.value(), &LoggedStartEvent::timestamp, output_batch); + if (!status.ok()) + return status; result = parser.ParseNumericField(utc_start_time_params_); if (!result.ok()) return result.status(); - PopulateRtcEventTimestamp(result.value(), &LoggedStartEvent::utc_start_time, - output_batch); + status = PopulateRtcEventTimestamp( + result.value(), &LoggedStartEvent::utc_start_time, output_batch); + if (!status.ok()) + return status; return RtcEventLogParseStatus::Success(); } diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc index f3f12192c4..0e98b2ff11 100644 --- a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc +++ b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc @@ -15,6 +15,12 @@ namespace webrtc { +constexpr RtcEventDefinition + RtcEventBweUpdateDelayBased::definition_; + RtcEventBweUpdateDelayBased::RtcEventBweUpdateDelayBased( int32_t bitrate_bps, BandwidthUsage detector_state) diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h index d6ebb060f7..981fb1e2de 100644 --- a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h +++ b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h @@ -13,14 +13,58 @@ #include +#include #include +#include +#include +#include "absl/strings/string_view.h" #include "api/network_state_predictor.h" #include "api/rtc_event_log/rtc_event.h" #include "api/units/timestamp.h" +#include "logging/rtc_event_log/events/rtc_event_definition.h" namespace webrtc { +// Separate the event log encoding from the enum values. +// As long as the enum values are the same as the encodings, +// the two conversion functions can be compiled to (roughly) +// a range check each. +template <> +class RtcEventLogEnum { + static constexpr uint64_t kBwNormal = 0; + static constexpr uint64_t kBwUnderusing = 1; + static constexpr uint64_t kBwOverusing = 2; + + public: + static uint64_t Encode(BandwidthUsage x) { + switch (x) { + case BandwidthUsage::kBwNormal: + return kBwNormal; + case BandwidthUsage::kBwUnderusing: + return kBwUnderusing; + case BandwidthUsage::kBwOverusing: + return kBwOverusing; + case BandwidthUsage::kLast: + RTC_DCHECK_NOTREACHED(); + } + RTC_DCHECK_NOTREACHED(); + return std::numeric_limits::max(); + } + static RtcEventLogParseStatusOr Decode(uint64_t x) { + switch (x) { + case kBwNormal: + return BandwidthUsage::kBwNormal; + case kBwUnderusing: + return BandwidthUsage::kBwUnderusing; + case kBwOverusing: + return BandwidthUsage::kBwOverusing; + } + return RtcEventLogParseStatus::Error("Failed to decode BandwidthUsage enum", + __FILE__, __LINE__); + } +}; + struct LoggedBweDelayBasedUpdate { LoggedBweDelayBasedUpdate() = default; LoggedBweDelayBasedUpdate(Timestamp timestamp, @@ -54,11 +98,36 @@ class RtcEventBweUpdateDelayBased final : public RtcEvent { int32_t bitrate_bps() const { return bitrate_bps_; } BandwidthUsage detector_state() const { return detector_state_; } + static std::string Encode(rtc::ArrayView batch) { + return RtcEventBweUpdateDelayBased::definition_.EncodeBatch(batch); + } + + static RtcEventLogParseStatus Parse( + absl::string_view s, + bool batched, + std::vector& output) { + return RtcEventBweUpdateDelayBased::definition_.ParseBatch(s, batched, + output); + } + private: RtcEventBweUpdateDelayBased(const RtcEventBweUpdateDelayBased& other); const int32_t bitrate_bps_; const BandwidthUsage detector_state_; + + static constexpr RtcEventDefinition + definition_{ + {"BweDelayBased", RtcEventBweUpdateDelayBased::kType}, + {&RtcEventBweUpdateDelayBased::bitrate_bps_, + &LoggedBweDelayBasedUpdate::bitrate_bps, + {"bitrate_bps", /*id=*/1, FieldType::kVarInt, /*width=*/32}}, + {&RtcEventBweUpdateDelayBased::detector_state_, + &LoggedBweDelayBasedUpdate::detector_state, + {"detector_state", /*id=*/2, FieldType::kVarInt, /*width=*/64}}}; }; } // namespace webrtc diff --git a/logging/rtc_event_log/events/rtc_event_definition.h b/logging/rtc_event_log/events/rtc_event_definition.h index 43dd7eb18b..8688c5fc7b 100644 --- a/logging/rtc_event_log/events/rtc_event_definition.h +++ b/logging/rtc_event_log/events/rtc_event_definition.h @@ -67,7 +67,10 @@ class RtcEventDefinitionImpl { parser.ParseNumericField(field_.params); if (!result.ok()) return result.status(); - PopulateRtcEventMember(result.value(), field_.logged_member, output_batch); + auto status = PopulateRtcEventMember(result.value(), field_.logged_member, + output_batch); + if (!status.ok()) + return status; return rest_.ParseImpl(parser, output_batch); } @@ -131,12 +134,12 @@ class RtcEventDefinition { parser.ParseNumericField(timestamp_params); if (!result.ok()) return result.status(); - PopulateRtcEventTimestamp(result.value(), &LoggedType::timestamp, - output_batch); + status = PopulateRtcEventTimestamp(result.value(), &LoggedType::timestamp, + output_batch); + if (!status.ok()) + return status; return fields_.ParseImpl(parser, output_batch); - - return RtcEventLogParseStatus::Success(); } private: diff --git a/logging/rtc_event_log/events/rtc_event_end_log.cc b/logging/rtc_event_log/events/rtc_event_end_log.cc index fa9930a833..52abf9e842 100644 --- a/logging/rtc_event_log/events/rtc_event_end_log.cc +++ b/logging/rtc_event_log/events/rtc_event_end_log.cc @@ -47,8 +47,10 @@ RtcEventLogParseStatus RtcEventEndLog::Parse( parser.ParseNumericField(timestamp_params); if (!result.ok()) return result.status(); - PopulateRtcEventTimestamp(result.value(), &LoggedStopEvent::timestamp, - output_batch); + status = PopulateRtcEventTimestamp(result.value(), + &LoggedStopEvent::timestamp, output_batch); + if (!status.ok()) + return status; return RtcEventLogParseStatus::Success(); } diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding.h b/logging/rtc_event_log/events/rtc_event_field_encoding.h index 8376a8b8a5..33b77b80f5 100644 --- a/logging/rtc_event_log/events/rtc_event_field_encoding.h +++ b/logging/rtc_event_log/events/rtc_event_field_encoding.h @@ -93,5 +93,87 @@ std::string EncodeDeltasV3(FixedLengthEncodingParametersV3 params, uint64_t base, rtc::ArrayView values); +// Given a batch of RtcEvents and a member pointer, extract that +// member from each event in the batch. Signed integer members are +// encoded as unsigned, and the bitsize increased so the result can +// represented as a std::vector. +// This is intended to be used in conjuction with +// EventEncoder::EncodeField to encode a batch of events as follows: +// auto values = ExtractRtcEventMember(batch, RtcEventFoo::timestamp_ms); +// encoder.EncodeField(timestamp_params, values) +template ::value, bool> = true> +std::vector ExtractRtcEventMember( + rtc::ArrayView batch, + const T E::*member) { + std::vector values; + values.reserve(batch.size()); + for (const RtcEvent* event : batch) { + RTC_CHECK_EQ(event->GetType(), E::kType); + T value = static_cast(event)->*member; + values.push_back(EncodeAsUnsigned(value)); + } + return values; +} + +// Extract an optional field from a batch of RtcEvents. +// The function returns a vector of positions in addition to the vector of +// values. The vector `positions` has the same length as the batch where +// `positions[i] == true` iff the batch[i]->member has a value. +// The values vector only contains the values that exists, so it +// may be shorter than the batch. +template ::value, bool> = true> +ValuesWithPositions ExtractRtcEventMember(rtc::ArrayView batch, + const absl::optional E::*member) { + ValuesWithPositions result; + result.position_mask.reserve(batch.size()); + result.values.reserve(batch.size()); + for (const RtcEvent* event : batch) { + RTC_CHECK_EQ(event->GetType(), E::kType); + absl::optional field = static_cast(event)->*member; + result.position_mask.push_back(field.has_value()); + if (field.has_value()) { + result.values.push_back(EncodeAsUnsigned(field.value())); + } + } + return result; +} + +// Extract an enum field from a batch of RtcEvents. +// Requires specializing RtcEventLogEnum for the enum type T. +template ::value, bool> = true> +std::vector ExtractRtcEventMember( + rtc::ArrayView batch, + const T E::*member) { + std::vector values; + values.reserve(batch.size()); + for (const RtcEvent* event : batch) { + RTC_CHECK_EQ(event->GetType(), E::kType); + T value = static_cast(event)->*member; + values.push_back(RtcEventLogEnum::Encode(value)); + } + return values; +} + +// Extract a string field from a batch of RtcEvents. +template +std::vector ExtractRtcEventMember( + rtc::ArrayView batch, + const std::string E::*member) { + std::vector values; + values.reserve(batch.size()); + for (const RtcEvent* event : batch) { + RTC_CHECK_EQ(event->GetType(), E::kType); + absl::string_view str = static_cast(event)->*member; + values.push_back(str); + } + return values; +} + } // namespace webrtc #endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_ diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h index 6b0270b127..1e0ead67fa 100644 --- a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h +++ b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h @@ -174,5 +174,110 @@ class EventParser { uint64_t last_field_id_ = FieldParameters::kTimestampField; }; +// Inverse of the ExtractRtcEventMember function used when parsing +// a log. Uses a vector of values to populate a specific field in a +// vector of structs. +template ::value, bool> = true> +ABSL_MUST_USE_RESULT RtcEventLogParseStatus +PopulateRtcEventMember(const rtc::ArrayView values, + T E::*member, + rtc::ArrayView output) { + size_t batch_size = values.size(); + RTC_CHECK_EQ(output.size(), batch_size); + for (size_t i = 0; i < batch_size; ++i) { + output[i].*member = DecodeFromUnsignedToType(values[i]); + } + return RtcEventLogParseStatus::Success(); +} + +// Same as above, but for optional fields. +template ::value, bool> = true> +ABSL_MUST_USE_RESULT RtcEventLogParseStatus +PopulateRtcEventMember(const rtc::ArrayView positions, + const rtc::ArrayView values, + absl::optional E::*member, + rtc::ArrayView output) { + size_t batch_size = positions.size(); + RTC_CHECK_EQ(output.size(), batch_size); + RTC_CHECK_LE(values.size(), batch_size); + auto value_it = values.begin(); + for (size_t i = 0; i < batch_size; ++i) { + if (positions[i]) { + RTC_CHECK(value_it != values.end()); + output[i].*member = DecodeFromUnsignedToType(value_it); + ++value_it; + } else { + output[i].*member = absl::nullopt; + } + } + RTC_CHECK(value_it == values.end()); + return RtcEventLogParseStatus::Success(); +} + +// Same as above, but for enum fields. +template ::value, bool> = true> +ABSL_MUST_USE_RESULT RtcEventLogParseStatus +PopulateRtcEventMember(const rtc::ArrayView values, + T E::*member, + rtc::ArrayView output) { + size_t batch_size = values.size(); + RTC_CHECK_EQ(output.size(), batch_size); + for (size_t i = 0; i < batch_size; ++i) { + auto result = RtcEventLogEnum::Decode(values[i]); + if (!result.ok()) { + return result.status(); + } + output[i].*member = result.value(); + } + return RtcEventLogParseStatus::Success(); +} + +// Same as above, but for string fields. +template +ABSL_MUST_USE_RESULT RtcEventLogParseStatus +PopulateRtcEventMember(const rtc::ArrayView values, + std::string E::*member, + rtc::ArrayView output) { + size_t batch_size = values.size(); + RTC_CHECK_EQ(output.size(), batch_size); + for (size_t i = 0; i < batch_size; ++i) { + output[i].*member = values[i]; + } + return RtcEventLogParseStatus::Success(); +} + +// Same as above, but for Timestamp fields. +// N.B. Assumes that the encoded value uses millisecond precision. +template +ABSL_MUST_USE_RESULT RtcEventLogParseStatus +PopulateRtcEventTimestamp(const rtc::ArrayView& values, + Timestamp E::*timestamp, + rtc::ArrayView output) { + size_t batch_size = values.size(); + RTC_CHECK_EQ(batch_size, output.size()); + for (size_t i = 0; i < batch_size; ++i) { + output[i].*timestamp = + Timestamp::Millis(DecodeFromUnsignedToType(values[i])); + } + return RtcEventLogParseStatus::Success(); +} + +template +rtc::ArrayView ExtendLoggedBatch(std::vector& output, + size_t new_elements) { + size_t old_size = output.size(); + output.insert(output.end(), old_size + new_elements, E()); + rtc::ArrayView output_batch = output; + output_batch.subview(old_size); + RTC_DCHECK_EQ(output_batch.size(), new_elements); + return output_batch; +} + } // namespace webrtc #endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_ diff --git a/logging/rtc_event_log/events/rtc_event_field_extraction.h b/logging/rtc_event_log/events/rtc_event_field_extraction.h index 0e0fffe90a..eb9d67f1c2 100644 --- a/logging/rtc_event_log/events/rtc_event_field_extraction.h +++ b/logging/rtc_event_log/events/rtc_event_field_extraction.h @@ -56,29 +56,16 @@ T DecodeFromUnsignedToType(uint64_t value) { return static_cast(value); } -// Given a batch of RtcEvents and a member pointer, extract that -// member from each event in the batch. Signed integer members are -// encoded as unsigned, and the bitsize increased so the result can -// represented as a std::vector. -// This is intended to be used in conjuction with -// EventEncoder::EncodeField to encode a batch of events as follows: -// auto values = ExtractRtcEventMember(batch, RtcEventFoo::timestamp_ms); -// encoder.EncodeField(timestamp_params, values) -template ::value, bool> = true> -std::vector ExtractRtcEventMember( - rtc::ArrayView batch, - const T E::*member) { - std::vector values; - values.reserve(batch.size()); - for (const RtcEvent* event : batch) { - RTC_CHECK_EQ(event->GetType(), E::kType); - T value = static_cast(event)->*member; - values.push_back(EncodeAsUnsigned(value)); - } - return values; -} +// RtcEventLogEnum defines a mapping between an enum T +// and the event log encodings. To log a new enum type T, +// specialize RtcEventLogEnum and add static methods +// static uint64_t Encode(T x) {} +// static RtcEventLogParseStatusOr Decode(uint64_t x) {} +template +class RtcEventLogEnum { + static_assert(sizeof(T) != sizeof(T), + "Missing specialisation of RtcEventLogEnum for type"); +}; // Represents a vector> optional_values // as a bit-vector `position_mask` which identifies the positions @@ -92,119 +79,6 @@ struct ValuesWithPositions { std::vector values; }; -// Same as above but for optional fields. It returns a struct -// containing a vector of positions in addition to the vector of values. -// The vector `positions` has the same length as the batch where -// `positions[i] == true` iff the batch[i]->member has a value. -// The values vector only contains the values that exists, so it -// may be shorter than the batch. -template ::value, bool> = true> -ValuesWithPositions ExtractRtcEventMember(rtc::ArrayView batch, - const absl::optional E::*member) { - ValuesWithPositions result; - result.position_mask.reserve(batch.size()); - result.values.reserve(batch.size()); - for (const RtcEvent* event : batch) { - RTC_CHECK_EQ(event->GetType(), E::kType); - absl::optional field = static_cast(event)->*member; - result.position_mask.push_back(field.has_value()); - if (field.has_value()) { - result.values.push_back(EncodeAsUnsigned(field.value())); - } - } - return result; -} - -template -std::vector ExtractRtcEventMember( - rtc::ArrayView batch, - const std::string E::*member) { - std::vector values; - values.reserve(batch.size()); - for (const RtcEvent* event : batch) { - RTC_CHECK_EQ(event->GetType(), E::kType); - absl::string_view str = static_cast(event)->*member; - values.push_back(str); - } - return values; -} - -// Inverse of the ExtractRtcEventMember function used when parsing -// a log. Uses a vector of values to populate a specific field in a -// vector of structs. -template ::value, bool> = true> -void PopulateRtcEventMember(const rtc::ArrayView values, - T E::*member, - rtc::ArrayView output) { - size_t batch_size = values.size(); - RTC_CHECK_EQ(output.size(), batch_size); - for (size_t i = 0; i < batch_size; ++i) { - output[i].*member = DecodeFromUnsignedToType(values[i]); - } -} - -// Same as above, but for optional fields. -template ::value, bool> = true> -void PopulateRtcEventMember(const rtc::ArrayView positions, - const rtc::ArrayView values, - absl::optional E::*member, - rtc::ArrayView output) { - size_t batch_size = positions.size(); - RTC_CHECK_EQ(output.size(), batch_size); - RTC_CHECK_LE(values.size(), batch_size); - auto value_it = values.begin(); - for (size_t i = 0; i < batch_size; ++i) { - if (positions[i]) { - RTC_CHECK(value_it != values.end()); - output[i].*member = DecodeFromUnsignedToType(value_it); - ++value_it; - } else { - output[i].*member = absl::nullopt; - } - } - RTC_CHECK(value_it == values.end()); -} - -template -void PopulateRtcEventMember(const rtc::ArrayView values, - std::string E::*member, - rtc::ArrayView output) { - size_t batch_size = values.size(); - RTC_CHECK_EQ(output.size(), batch_size); - for (size_t i = 0; i < batch_size; ++i) { - output[i].*member = values[i]; - } -} - -template -void PopulateRtcEventTimestamp(const rtc::ArrayView& values, - Timestamp E::*timestamp, - rtc::ArrayView output) { - size_t batch_size = values.size(); - RTC_CHECK_EQ(batch_size, output.size()); - for (size_t i = 0; i < batch_size; ++i) { - output[i].*timestamp = - Timestamp::Millis(DecodeFromUnsignedToType(values[i])); - } -} - -template -rtc::ArrayView ExtendLoggedBatch(std::vector& output, - size_t new_elements) { - size_t old_size = output.size(); - output.insert(output.end(), old_size + new_elements, E()); - rtc::ArrayView output_batch = output; - output_batch.subview(old_size); - RTC_DCHECK_EQ(output_batch.size(), new_elements); - return output_batch; -} - } // namespace webrtc #endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_EXTRACTION_H_ diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc index 3742aba50b..3da42f8fd5 100644 --- a/logging/rtc_event_log/rtc_event_log_parser.cc +++ b/logging/rtc_event_log/rtc_event_log_parser.cc @@ -1425,7 +1425,14 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternalV3( case static_cast(RtcEvent::Type::AlrStateEvent): RtcEventAlrState::Parse(event_fields, batched, alr_state_events_); break; - // ADD NEW EVENTS HERE + case static_cast(RtcEvent::Type::AudioPlayout): + RtcEventAudioPlayout::Parse(event_fields, batched, + audio_playout_events_); + break; + case static_cast(RtcEvent::Type::BweUpdateDelayBased): + RtcEventBweUpdateDelayBased::Parse(event_fields, batched, + bwe_delay_updates_); + break; } }