1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "logging/rtc_event_log/rtc_event_log_parser.h"
12
13 #include <stdint.h>
14 #include <string.h>
15
16 #include <algorithm>
17 #include <fstream>
18 #include <istream> // no-presubmit-check TODO(webrtc:8982)
19 #include <limits>
20 #include <map>
21 #include <utility>
22
23 #include "absl/memory/memory.h"
24 #include "absl/types/optional.h"
25 #include "api/rtc_event_log/rtc_event_log.h"
26 #include "api/rtp_headers.h"
27 #include "api/rtp_parameters.h"
28 #include "logging/rtc_event_log/encoder/blob_encoding.h"
29 #include "logging/rtc_event_log/encoder/delta_encoding.h"
30 #include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
31 #include "logging/rtc_event_log/rtc_event_processor.h"
32 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
33 #include "modules/include/module_common_types.h"
34 #include "modules/include/module_common_types_public.h"
35 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
36 #include "modules/rtp_rtcp/include/rtp_cvo.h"
37 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
38 #include "modules/rtp_rtcp/source/byte_io.h"
39 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
40 #include "modules/rtp_rtcp/source/rtp_utility.h"
41 #include "rtc_base/checks.h"
42 #include "rtc_base/logging.h"
43 #include "rtc_base/numerics/safe_conversions.h"
44 #include "rtc_base/numerics/sequence_number_util.h"
45 #include "rtc_base/protobuf_utils.h"
46
47 // These macros were added to convert existing code using RTC_CHECKs
48 // to returning a Status object instead. Macros are necessary (over
49 // e.g. helper functions) since we want to return from the current
50 // function.
51 #define RTC_PARSE_CHECK_OR_RETURN(X) \
52 do { \
53 if (!(X)) \
54 return ParsedRtcEventLog::ParseStatus::Error(#X, __FILE__, __LINE__); \
55 } while (0)
56
57 #define RTC_PARSE_CHECK_OR_RETURN_OP(OP, X, Y) \
58 do { \
59 if (!((X)OP(Y))) \
60 return ParsedRtcEventLog::ParseStatus::Error(#X #OP #Y, __FILE__, \
61 __LINE__); \
62 } while (0)
63
64 #define RTC_PARSE_CHECK_OR_RETURN_EQ(X, Y) \
65 RTC_PARSE_CHECK_OR_RETURN_OP(==, X, Y)
66
67 #define RTC_PARSE_CHECK_OR_RETURN_NE(X, Y) \
68 RTC_PARSE_CHECK_OR_RETURN_OP(!=, X, Y)
69
70 #define RTC_PARSE_CHECK_OR_RETURN_LT(X, Y) RTC_PARSE_CHECK_OR_RETURN_OP(<, X, Y)
71
72 #define RTC_PARSE_CHECK_OR_RETURN_LE(X, Y) \
73 RTC_PARSE_CHECK_OR_RETURN_OP(<=, X, Y)
74
75 #define RTC_PARSE_CHECK_OR_RETURN_GT(X, Y) RTC_PARSE_CHECK_OR_RETURN_OP(>, X, Y)
76
77 #define RTC_PARSE_CHECK_OR_RETURN_GE(X, Y) \
78 RTC_PARSE_CHECK_OR_RETURN_OP(>=, X, Y)
79
80 #define RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(X, M) \
81 do { \
82 if (X) { \
83 RTC_LOG(LS_WARNING) << (M); \
84 return ParsedRtcEventLog::ParseStatus::Success(); \
85 } \
86 } while (0)
87
88 #define RTC_RETURN_IF_ERROR(X) \
89 do { \
90 const ParsedRtcEventLog::ParseStatus _rtc_parse_status(X); \
91 if (!_rtc_parse_status.ok()) { \
92 return _rtc_parse_status; \
93 } \
94 } while (0)
95
96 using webrtc_event_logging::ToSigned;
97 using webrtc_event_logging::ToUnsigned;
98
99 namespace webrtc {
100
101 namespace {
102 constexpr size_t kIpv4Overhead = 20;
103 constexpr size_t kIpv6Overhead = 40;
104 constexpr size_t kUdpOverhead = 8;
105 constexpr size_t kSrtpOverhead = 10;
106 constexpr size_t kStunOverhead = 4;
107 constexpr uint16_t kDefaultOverhead =
108 kUdpOverhead + kSrtpOverhead + kIpv4Overhead;
109
110 constexpr char kIncompleteLogError[] =
111 "Could not parse the entire log. Only the beginning will be used.";
112
113 struct MediaStreamInfo {
114 MediaStreamInfo() = default;
MediaStreamInfowebrtc::__anonf5bf4f890111::MediaStreamInfo115 MediaStreamInfo(LoggedMediaType media_type, bool rtx)
116 : media_type(media_type), rtx(rtx) {}
117 LoggedMediaType media_type = LoggedMediaType::kUnknown;
118 bool rtx = false;
119 SeqNumUnwrapper<uint32_t> unwrap_capture_ticks;
120 };
121
122 template <typename Iterable>
AddRecvStreamInfos(std::map<uint32_t,MediaStreamInfo> * streams,const Iterable configs,LoggedMediaType media_type)123 void AddRecvStreamInfos(std::map<uint32_t, MediaStreamInfo>* streams,
124 const Iterable configs,
125 LoggedMediaType media_type) {
126 for (auto& conf : configs) {
127 streams->insert({conf.config.remote_ssrc, {media_type, false}});
128 if (conf.config.rtx_ssrc != 0)
129 streams->insert({conf.config.rtx_ssrc, {media_type, true}});
130 }
131 }
132 template <typename Iterable>
AddSendStreamInfos(std::map<uint32_t,MediaStreamInfo> * streams,const Iterable configs,LoggedMediaType media_type)133 void AddSendStreamInfos(std::map<uint32_t, MediaStreamInfo>* streams,
134 const Iterable configs,
135 LoggedMediaType media_type) {
136 for (auto& conf : configs) {
137 streams->insert({conf.config.local_ssrc, {media_type, false}});
138 if (conf.config.rtx_ssrc != 0)
139 streams->insert({conf.config.rtx_ssrc, {media_type, true}});
140 }
141 }
142 struct OverheadChangeEvent {
143 Timestamp timestamp;
144 uint16_t overhead;
145 };
GetOverheadChangingEvents(const std::vector<InferredRouteChangeEvent> & route_changes,PacketDirection direction)146 std::vector<OverheadChangeEvent> GetOverheadChangingEvents(
147 const std::vector<InferredRouteChangeEvent>& route_changes,
148 PacketDirection direction) {
149 std::vector<OverheadChangeEvent> overheads;
150 for (auto& event : route_changes) {
151 uint16_t new_overhead = direction == PacketDirection::kIncomingPacket
152 ? event.return_overhead
153 : event.send_overhead;
154 if (overheads.empty() || new_overhead != overheads.back().overhead) {
155 overheads.push_back({event.log_time, new_overhead});
156 }
157 }
158 return overheads;
159 }
160
IdenticalRtcpContents(const std::vector<uint8_t> & last_rtcp,absl::string_view new_rtcp)161 bool IdenticalRtcpContents(const std::vector<uint8_t>& last_rtcp,
162 absl::string_view new_rtcp) {
163 if (last_rtcp.size() != new_rtcp.size())
164 return false;
165 return memcmp(last_rtcp.data(), new_rtcp.data(), new_rtcp.size()) == 0;
166 }
167
168 // Conversion functions for legacy wire format.
GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode)169 RtcpMode GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode) {
170 switch (rtcp_mode) {
171 case rtclog::VideoReceiveConfig::RTCP_COMPOUND:
172 return RtcpMode::kCompound;
173 case rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE:
174 return RtcpMode::kReducedSize;
175 }
176 RTC_NOTREACHED();
177 return RtcpMode::kOff;
178 }
179
GetRuntimeDetectorState(rtclog::DelayBasedBweUpdate::DetectorState detector_state)180 BandwidthUsage GetRuntimeDetectorState(
181 rtclog::DelayBasedBweUpdate::DetectorState detector_state) {
182 switch (detector_state) {
183 case rtclog::DelayBasedBweUpdate::BWE_NORMAL:
184 return BandwidthUsage::kBwNormal;
185 case rtclog::DelayBasedBweUpdate::BWE_UNDERUSING:
186 return BandwidthUsage::kBwUnderusing;
187 case rtclog::DelayBasedBweUpdate::BWE_OVERUSING:
188 return BandwidthUsage::kBwOverusing;
189 }
190 RTC_NOTREACHED();
191 return BandwidthUsage::kBwNormal;
192 }
193
GetRuntimeIceCandidatePairConfigType(rtclog::IceCandidatePairConfig::IceCandidatePairConfigType type)194 IceCandidatePairConfigType GetRuntimeIceCandidatePairConfigType(
195 rtclog::IceCandidatePairConfig::IceCandidatePairConfigType type) {
196 switch (type) {
197 case rtclog::IceCandidatePairConfig::ADDED:
198 return IceCandidatePairConfigType::kAdded;
199 case rtclog::IceCandidatePairConfig::UPDATED:
200 return IceCandidatePairConfigType::kUpdated;
201 case rtclog::IceCandidatePairConfig::DESTROYED:
202 return IceCandidatePairConfigType::kDestroyed;
203 case rtclog::IceCandidatePairConfig::SELECTED:
204 return IceCandidatePairConfigType::kSelected;
205 }
206 RTC_NOTREACHED();
207 return IceCandidatePairConfigType::kAdded;
208 }
209
GetRuntimeIceCandidateType(rtclog::IceCandidatePairConfig::IceCandidateType type)210 IceCandidateType GetRuntimeIceCandidateType(
211 rtclog::IceCandidatePairConfig::IceCandidateType type) {
212 switch (type) {
213 case rtclog::IceCandidatePairConfig::LOCAL:
214 return IceCandidateType::kLocal;
215 case rtclog::IceCandidatePairConfig::STUN:
216 return IceCandidateType::kStun;
217 case rtclog::IceCandidatePairConfig::PRFLX:
218 return IceCandidateType::kPrflx;
219 case rtclog::IceCandidatePairConfig::RELAY:
220 return IceCandidateType::kRelay;
221 case rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
222 return IceCandidateType::kUnknown;
223 }
224 RTC_NOTREACHED();
225 return IceCandidateType::kUnknown;
226 }
227
GetRuntimeIceCandidatePairProtocol(rtclog::IceCandidatePairConfig::Protocol protocol)228 IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
229 rtclog::IceCandidatePairConfig::Protocol protocol) {
230 switch (protocol) {
231 case rtclog::IceCandidatePairConfig::UDP:
232 return IceCandidatePairProtocol::kUdp;
233 case rtclog::IceCandidatePairConfig::TCP:
234 return IceCandidatePairProtocol::kTcp;
235 case rtclog::IceCandidatePairConfig::SSLTCP:
236 return IceCandidatePairProtocol::kSsltcp;
237 case rtclog::IceCandidatePairConfig::TLS:
238 return IceCandidatePairProtocol::kTls;
239 case rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL:
240 return IceCandidatePairProtocol::kUnknown;
241 }
242 RTC_NOTREACHED();
243 return IceCandidatePairProtocol::kUnknown;
244 }
245
GetRuntimeIceCandidatePairAddressFamily(rtclog::IceCandidatePairConfig::AddressFamily address_family)246 IceCandidatePairAddressFamily GetRuntimeIceCandidatePairAddressFamily(
247 rtclog::IceCandidatePairConfig::AddressFamily address_family) {
248 switch (address_family) {
249 case rtclog::IceCandidatePairConfig::IPV4:
250 return IceCandidatePairAddressFamily::kIpv4;
251 case rtclog::IceCandidatePairConfig::IPV6:
252 return IceCandidatePairAddressFamily::kIpv6;
253 case rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY:
254 return IceCandidatePairAddressFamily::kUnknown;
255 }
256 RTC_NOTREACHED();
257 return IceCandidatePairAddressFamily::kUnknown;
258 }
259
GetRuntimeIceCandidateNetworkType(rtclog::IceCandidatePairConfig::NetworkType network_type)260 IceCandidateNetworkType GetRuntimeIceCandidateNetworkType(
261 rtclog::IceCandidatePairConfig::NetworkType network_type) {
262 switch (network_type) {
263 case rtclog::IceCandidatePairConfig::ETHERNET:
264 return IceCandidateNetworkType::kEthernet;
265 case rtclog::IceCandidatePairConfig::LOOPBACK:
266 return IceCandidateNetworkType::kLoopback;
267 case rtclog::IceCandidatePairConfig::WIFI:
268 return IceCandidateNetworkType::kWifi;
269 case rtclog::IceCandidatePairConfig::VPN:
270 return IceCandidateNetworkType::kVpn;
271 case rtclog::IceCandidatePairConfig::CELLULAR:
272 return IceCandidateNetworkType::kCellular;
273 case rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE:
274 return IceCandidateNetworkType::kUnknown;
275 }
276 RTC_NOTREACHED();
277 return IceCandidateNetworkType::kUnknown;
278 }
279
GetRuntimeIceCandidatePairEventType(rtclog::IceCandidatePairEvent::IceCandidatePairEventType type)280 IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
281 rtclog::IceCandidatePairEvent::IceCandidatePairEventType type) {
282 switch (type) {
283 case rtclog::IceCandidatePairEvent::CHECK_SENT:
284 return IceCandidatePairEventType::kCheckSent;
285 case rtclog::IceCandidatePairEvent::CHECK_RECEIVED:
286 return IceCandidatePairEventType::kCheckReceived;
287 case rtclog::IceCandidatePairEvent::CHECK_RESPONSE_SENT:
288 return IceCandidatePairEventType::kCheckResponseSent;
289 case rtclog::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED:
290 return IceCandidatePairEventType::kCheckResponseReceived;
291 }
292 RTC_NOTREACHED();
293 return IceCandidatePairEventType::kCheckSent;
294 }
295
296 // Reads a VarInt from |stream| and returns it. Also writes the read bytes to
297 // |buffer| starting |bytes_written| bytes into the buffer. |bytes_written| is
298 // incremented for each written byte.
ParseVarInt(std::istream & stream,char * buffer,size_t * bytes_written)299 ParsedRtcEventLog::ParseStatusOr<uint64_t> ParseVarInt(
300 std::istream& stream, // no-presubmit-check TODO(webrtc:8982)
301 char* buffer,
302 size_t* bytes_written) {
303 uint64_t varint = 0;
304 for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
305 // The most significant bit of each byte is 0 if it is the last byte in
306 // the varint and 1 otherwise. Thus, we take the 7 least significant bits
307 // of each byte and shift them 7 bits for each byte read previously to get
308 // the (unsigned) integer.
309 int byte = stream.get();
310 RTC_PARSE_CHECK_OR_RETURN(!stream.eof());
311 RTC_DCHECK_GE(byte, 0);
312 RTC_DCHECK_LE(byte, 255);
313 varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
314 buffer[*bytes_written] = byte;
315 *bytes_written += 1;
316 if ((byte & 0x80) == 0) {
317 return varint;
318 }
319 }
320 RTC_PARSE_CHECK_OR_RETURN(false);
321 }
322
GetHeaderExtensions(std::vector<RtpExtension> * header_extensions,const RepeatedPtrField<rtclog::RtpHeaderExtension> & proto_header_extensions)323 ParsedRtcEventLog::ParseStatus GetHeaderExtensions(
324 std::vector<RtpExtension>* header_extensions,
325 const RepeatedPtrField<rtclog::RtpHeaderExtension>&
326 proto_header_extensions) {
327 header_extensions->clear();
328 for (auto& p : proto_header_extensions) {
329 RTC_PARSE_CHECK_OR_RETURN(p.has_name());
330 RTC_PARSE_CHECK_OR_RETURN(p.has_id());
331 const std::string& name = p.name();
332 int id = p.id();
333 header_extensions->push_back(RtpExtension(name, id));
334 }
335 return ParsedRtcEventLog::ParseStatus::Success();
336 }
337
338 template <typename ProtoType, typename LoggedType>
StoreRtpPackets(const ProtoType & proto,std::map<uint32_t,std::vector<LoggedType>> * rtp_packets_map)339 ParsedRtcEventLog::ParseStatus StoreRtpPackets(
340 const ProtoType& proto,
341 std::map<uint32_t, std::vector<LoggedType>>* rtp_packets_map) {
342 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
343 RTC_PARSE_CHECK_OR_RETURN(proto.has_marker());
344 RTC_PARSE_CHECK_OR_RETURN(proto.has_payload_type());
345 RTC_PARSE_CHECK_OR_RETURN(proto.has_sequence_number());
346 RTC_PARSE_CHECK_OR_RETURN(proto.has_rtp_timestamp());
347 RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
348 RTC_PARSE_CHECK_OR_RETURN(proto.has_payload_size());
349 RTC_PARSE_CHECK_OR_RETURN(proto.has_header_size());
350 RTC_PARSE_CHECK_OR_RETURN(proto.has_padding_size());
351
352 // Base event
353 {
354 RTPHeader header;
355 header.markerBit = rtc::checked_cast<bool>(proto.marker());
356 header.payloadType = rtc::checked_cast<uint8_t>(proto.payload_type());
357 header.sequenceNumber =
358 rtc::checked_cast<uint16_t>(proto.sequence_number());
359 header.timestamp = rtc::checked_cast<uint32_t>(proto.rtp_timestamp());
360 header.ssrc = rtc::checked_cast<uint32_t>(proto.ssrc());
361 header.numCSRCs = 0; // TODO(terelius): Implement CSRC.
362 header.paddingLength = rtc::checked_cast<size_t>(proto.padding_size());
363 header.headerLength = rtc::checked_cast<size_t>(proto.header_size());
364 // TODO(terelius): Should we implement payload_type_frequency?
365 if (proto.has_transport_sequence_number()) {
366 header.extension.hasTransportSequenceNumber = true;
367 header.extension.transportSequenceNumber =
368 rtc::checked_cast<uint16_t>(proto.transport_sequence_number());
369 }
370 if (proto.has_transmission_time_offset()) {
371 header.extension.hasTransmissionTimeOffset = true;
372 header.extension.transmissionTimeOffset =
373 rtc::checked_cast<int32_t>(proto.transmission_time_offset());
374 }
375 if (proto.has_absolute_send_time()) {
376 header.extension.hasAbsoluteSendTime = true;
377 header.extension.absoluteSendTime =
378 rtc::checked_cast<uint32_t>(proto.absolute_send_time());
379 }
380 if (proto.has_video_rotation()) {
381 header.extension.hasVideoRotation = true;
382 header.extension.videoRotation = ConvertCVOByteToVideoRotation(
383 rtc::checked_cast<uint8_t>(proto.video_rotation()));
384 }
385 if (proto.has_audio_level()) {
386 RTC_PARSE_CHECK_OR_RETURN(proto.has_voice_activity());
387 header.extension.hasAudioLevel = true;
388 header.extension.voiceActivity =
389 rtc::checked_cast<bool>(proto.voice_activity());
390 const uint8_t audio_level =
391 rtc::checked_cast<uint8_t>(proto.audio_level());
392 RTC_PARSE_CHECK_OR_RETURN_LE(audio_level, 0x7Fu);
393 header.extension.audioLevel = audio_level;
394 } else {
395 RTC_PARSE_CHECK_OR_RETURN(!proto.has_voice_activity());
396 }
397 (*rtp_packets_map)[header.ssrc].emplace_back(
398 proto.timestamp_ms() * 1000, header, proto.header_size(),
399 proto.payload_size() + header.headerLength + header.paddingLength);
400 }
401
402 const size_t number_of_deltas =
403 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
404 if (number_of_deltas == 0) {
405 return ParsedRtcEventLog::ParseStatus::Success();
406 }
407
408 // timestamp_ms (event)
409 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
410 DecodeDeltas(proto.timestamp_ms_deltas(),
411 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
412 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
413
414 // marker (RTP base)
415 std::vector<absl::optional<uint64_t>> marker_values =
416 DecodeDeltas(proto.marker_deltas(), proto.marker(), number_of_deltas);
417 RTC_PARSE_CHECK_OR_RETURN_EQ(marker_values.size(), number_of_deltas);
418
419 // payload_type (RTP base)
420 std::vector<absl::optional<uint64_t>> payload_type_values = DecodeDeltas(
421 proto.payload_type_deltas(), proto.payload_type(), number_of_deltas);
422 RTC_PARSE_CHECK_OR_RETURN_EQ(payload_type_values.size(), number_of_deltas);
423
424 // sequence_number (RTP base)
425 std::vector<absl::optional<uint64_t>> sequence_number_values =
426 DecodeDeltas(proto.sequence_number_deltas(), proto.sequence_number(),
427 number_of_deltas);
428 RTC_PARSE_CHECK_OR_RETURN_EQ(sequence_number_values.size(), number_of_deltas);
429
430 // rtp_timestamp (RTP base)
431 std::vector<absl::optional<uint64_t>> rtp_timestamp_values = DecodeDeltas(
432 proto.rtp_timestamp_deltas(), proto.rtp_timestamp(), number_of_deltas);
433 RTC_PARSE_CHECK_OR_RETURN_EQ(rtp_timestamp_values.size(), number_of_deltas);
434
435 // ssrc (RTP base)
436 std::vector<absl::optional<uint64_t>> ssrc_values =
437 DecodeDeltas(proto.ssrc_deltas(), proto.ssrc(), number_of_deltas);
438 RTC_PARSE_CHECK_OR_RETURN_EQ(ssrc_values.size(), number_of_deltas);
439
440 // payload_size (RTP base)
441 std::vector<absl::optional<uint64_t>> payload_size_values = DecodeDeltas(
442 proto.payload_size_deltas(), proto.payload_size(), number_of_deltas);
443 RTC_PARSE_CHECK_OR_RETURN_EQ(payload_size_values.size(), number_of_deltas);
444
445 // header_size (RTP base)
446 std::vector<absl::optional<uint64_t>> header_size_values = DecodeDeltas(
447 proto.header_size_deltas(), proto.header_size(), number_of_deltas);
448 RTC_PARSE_CHECK_OR_RETURN_EQ(header_size_values.size(), number_of_deltas);
449
450 // padding_size (RTP base)
451 std::vector<absl::optional<uint64_t>> padding_size_values = DecodeDeltas(
452 proto.padding_size_deltas(), proto.padding_size(), number_of_deltas);
453 RTC_PARSE_CHECK_OR_RETURN_EQ(padding_size_values.size(), number_of_deltas);
454
455 // transport_sequence_number (RTP extension)
456 std::vector<absl::optional<uint64_t>> transport_sequence_number_values;
457 {
458 const absl::optional<uint64_t> base_transport_sequence_number =
459 proto.has_transport_sequence_number()
460 ? proto.transport_sequence_number()
461 : absl::optional<uint64_t>();
462 transport_sequence_number_values =
463 DecodeDeltas(proto.transport_sequence_number_deltas(),
464 base_transport_sequence_number, number_of_deltas);
465 RTC_PARSE_CHECK_OR_RETURN_EQ(transport_sequence_number_values.size(),
466 number_of_deltas);
467 }
468
469 // transmission_time_offset (RTP extension)
470 std::vector<absl::optional<uint64_t>> transmission_time_offset_values;
471 {
472 const absl::optional<uint64_t> unsigned_base_transmission_time_offset =
473 proto.has_transmission_time_offset()
474 ? ToUnsigned(proto.transmission_time_offset())
475 : absl::optional<uint64_t>();
476 transmission_time_offset_values =
477 DecodeDeltas(proto.transmission_time_offset_deltas(),
478 unsigned_base_transmission_time_offset, number_of_deltas);
479 RTC_PARSE_CHECK_OR_RETURN_EQ(transmission_time_offset_values.size(),
480 number_of_deltas);
481 }
482
483 // absolute_send_time (RTP extension)
484 std::vector<absl::optional<uint64_t>> absolute_send_time_values;
485 {
486 const absl::optional<uint64_t> base_absolute_send_time =
487 proto.has_absolute_send_time() ? proto.absolute_send_time()
488 : absl::optional<uint64_t>();
489 absolute_send_time_values =
490 DecodeDeltas(proto.absolute_send_time_deltas(), base_absolute_send_time,
491 number_of_deltas);
492 RTC_PARSE_CHECK_OR_RETURN_EQ(absolute_send_time_values.size(),
493 number_of_deltas);
494 }
495
496 // video_rotation (RTP extension)
497 std::vector<absl::optional<uint64_t>> video_rotation_values;
498 {
499 const absl::optional<uint64_t> base_video_rotation =
500 proto.has_video_rotation() ? proto.video_rotation()
501 : absl::optional<uint64_t>();
502 video_rotation_values = DecodeDeltas(proto.video_rotation_deltas(),
503 base_video_rotation, number_of_deltas);
504 RTC_PARSE_CHECK_OR_RETURN_EQ(video_rotation_values.size(),
505 number_of_deltas);
506 }
507
508 // audio_level (RTP extension)
509 std::vector<absl::optional<uint64_t>> audio_level_values;
510 {
511 const absl::optional<uint64_t> base_audio_level =
512 proto.has_audio_level() ? proto.audio_level()
513 : absl::optional<uint64_t>();
514 audio_level_values = DecodeDeltas(proto.audio_level_deltas(),
515 base_audio_level, number_of_deltas);
516 RTC_PARSE_CHECK_OR_RETURN_EQ(audio_level_values.size(), number_of_deltas);
517 }
518
519 // voice_activity (RTP extension)
520 std::vector<absl::optional<uint64_t>> voice_activity_values;
521 {
522 const absl::optional<uint64_t> base_voice_activity =
523 proto.has_voice_activity() ? proto.voice_activity()
524 : absl::optional<uint64_t>();
525 voice_activity_values = DecodeDeltas(proto.voice_activity_deltas(),
526 base_voice_activity, number_of_deltas);
527 RTC_PARSE_CHECK_OR_RETURN_EQ(voice_activity_values.size(),
528 number_of_deltas);
529 }
530
531 // Delta decoding
532 for (size_t i = 0; i < number_of_deltas; ++i) {
533 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
534 RTC_PARSE_CHECK_OR_RETURN(marker_values[i].has_value());
535 RTC_PARSE_CHECK_OR_RETURN(payload_type_values[i].has_value());
536 RTC_PARSE_CHECK_OR_RETURN(sequence_number_values[i].has_value());
537 RTC_PARSE_CHECK_OR_RETURN(rtp_timestamp_values[i].has_value());
538 RTC_PARSE_CHECK_OR_RETURN(ssrc_values[i].has_value());
539 RTC_PARSE_CHECK_OR_RETURN(payload_size_values[i].has_value());
540 RTC_PARSE_CHECK_OR_RETURN(header_size_values[i].has_value());
541 RTC_PARSE_CHECK_OR_RETURN(padding_size_values[i].has_value());
542
543 int64_t timestamp_ms;
544 RTC_PARSE_CHECK_OR_RETURN(
545 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
546
547 RTPHeader header;
548 header.markerBit = rtc::checked_cast<bool>(*marker_values[i]);
549 header.payloadType = rtc::checked_cast<uint8_t>(*payload_type_values[i]);
550 header.sequenceNumber =
551 rtc::checked_cast<uint16_t>(*sequence_number_values[i]);
552 header.timestamp = rtc::checked_cast<uint32_t>(*rtp_timestamp_values[i]);
553 header.ssrc = rtc::checked_cast<uint32_t>(*ssrc_values[i]);
554 header.numCSRCs = 0; // TODO(terelius): Implement CSRC.
555 header.paddingLength = rtc::checked_cast<size_t>(*padding_size_values[i]);
556 header.headerLength = rtc::checked_cast<size_t>(*header_size_values[i]);
557 // TODO(terelius): Should we implement payload_type_frequency?
558 if (transport_sequence_number_values.size() > i &&
559 transport_sequence_number_values[i].has_value()) {
560 header.extension.hasTransportSequenceNumber = true;
561 header.extension.transportSequenceNumber = rtc::checked_cast<uint16_t>(
562 transport_sequence_number_values[i].value());
563 }
564 if (transmission_time_offset_values.size() > i &&
565 transmission_time_offset_values[i].has_value()) {
566 header.extension.hasTransmissionTimeOffset = true;
567 int32_t transmission_time_offset;
568 RTC_PARSE_CHECK_OR_RETURN(
569 ToSigned(transmission_time_offset_values[i].value(),
570 &transmission_time_offset));
571 header.extension.transmissionTimeOffset = transmission_time_offset;
572 }
573 if (absolute_send_time_values.size() > i &&
574 absolute_send_time_values[i].has_value()) {
575 header.extension.hasAbsoluteSendTime = true;
576 header.extension.absoluteSendTime =
577 rtc::checked_cast<uint32_t>(absolute_send_time_values[i].value());
578 }
579 if (video_rotation_values.size() > i &&
580 video_rotation_values[i].has_value()) {
581 header.extension.hasVideoRotation = true;
582 header.extension.videoRotation = ConvertCVOByteToVideoRotation(
583 rtc::checked_cast<uint8_t>(video_rotation_values[i].value()));
584 }
585 if (audio_level_values.size() > i && audio_level_values[i].has_value()) {
586 RTC_PARSE_CHECK_OR_RETURN(voice_activity_values.size() > i &&
587 voice_activity_values[i].has_value());
588 header.extension.hasAudioLevel = true;
589 header.extension.voiceActivity =
590 rtc::checked_cast<bool>(voice_activity_values[i].value());
591 const uint8_t audio_level =
592 rtc::checked_cast<uint8_t>(audio_level_values[i].value());
593 RTC_PARSE_CHECK_OR_RETURN_LE(audio_level, 0x7Fu);
594 header.extension.audioLevel = audio_level;
595 } else {
596 RTC_PARSE_CHECK_OR_RETURN(voice_activity_values.size() <= i ||
597 !voice_activity_values[i].has_value());
598 }
599 (*rtp_packets_map)[header.ssrc].emplace_back(
600 1000 * timestamp_ms, header, header.headerLength,
601 payload_size_values[i].value() + header.headerLength +
602 header.paddingLength);
603 }
604 return ParsedRtcEventLog::ParseStatus::Success();
605 }
606
607 template <typename ProtoType, typename LoggedType>
StoreRtcpPackets(const ProtoType & proto,std::vector<LoggedType> * rtcp_packets,bool remove_duplicates)608 ParsedRtcEventLog::ParseStatus StoreRtcpPackets(
609 const ProtoType& proto,
610 std::vector<LoggedType>* rtcp_packets,
611 bool remove_duplicates) {
612 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
613 RTC_PARSE_CHECK_OR_RETURN(proto.has_raw_packet());
614
615 // TODO(terelius): Incoming RTCP may be delivered once for audio and once
616 // for video. As a work around, we remove the duplicated packets since they
617 // cause problems when analyzing the log or feeding it into the transport
618 // feedback adapter.
619 if (!remove_duplicates || rtcp_packets->empty() ||
620 !IdenticalRtcpContents(rtcp_packets->back().rtcp.raw_data,
621 proto.raw_packet())) {
622 // Base event
623 rtcp_packets->emplace_back(proto.timestamp_ms() * 1000, proto.raw_packet());
624 }
625
626 const size_t number_of_deltas =
627 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
628 if (number_of_deltas == 0) {
629 return ParsedRtcEventLog::ParseStatus::Success();
630 }
631
632 // timestamp_ms
633 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
634 DecodeDeltas(proto.timestamp_ms_deltas(),
635 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
636 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
637
638 // raw_packet
639 RTC_PARSE_CHECK_OR_RETURN(proto.has_raw_packet_blobs());
640 std::vector<absl::string_view> raw_packet_values =
641 DecodeBlobs(proto.raw_packet_blobs(), number_of_deltas);
642 RTC_PARSE_CHECK_OR_RETURN_EQ(raw_packet_values.size(), number_of_deltas);
643
644 // Delta decoding
645 for (size_t i = 0; i < number_of_deltas; ++i) {
646 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
647 int64_t timestamp_ms;
648 RTC_PARSE_CHECK_OR_RETURN(
649 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
650
651 // TODO(terelius): Incoming RTCP may be delivered once for audio and once
652 // for video. As a work around, we remove the duplicated packets since they
653 // cause problems when analyzing the log or feeding it into the transport
654 // feedback adapter.
655 if (remove_duplicates && !rtcp_packets->empty() &&
656 IdenticalRtcpContents(rtcp_packets->back().rtcp.raw_data,
657 raw_packet_values[i])) {
658 continue;
659 }
660 const size_t data_size = raw_packet_values[i].size();
661 const uint8_t* data =
662 reinterpret_cast<const uint8_t*>(raw_packet_values[i].data());
663 rtcp_packets->emplace_back(1000 * timestamp_ms, data, data_size);
664 }
665 return ParsedRtcEventLog::ParseStatus::Success();
666 }
667
StoreRtcpBlocks(int64_t timestamp_us,const uint8_t * packet_begin,const uint8_t * packet_end,std::vector<LoggedRtcpPacketSenderReport> * sr_list,std::vector<LoggedRtcpPacketReceiverReport> * rr_list,std::vector<LoggedRtcpPacketExtendedReports> * xr_list,std::vector<LoggedRtcpPacketRemb> * remb_list,std::vector<LoggedRtcpPacketNack> * nack_list,std::vector<LoggedRtcpPacketFir> * fir_list,std::vector<LoggedRtcpPacketPli> * pli_list,std::vector<LoggedRtcpPacketTransportFeedback> * transport_feedback_list,std::vector<LoggedRtcpPacketLossNotification> * loss_notification_list)668 ParsedRtcEventLog::ParseStatus StoreRtcpBlocks(
669 int64_t timestamp_us,
670 const uint8_t* packet_begin,
671 const uint8_t* packet_end,
672 std::vector<LoggedRtcpPacketSenderReport>* sr_list,
673 std::vector<LoggedRtcpPacketReceiverReport>* rr_list,
674 std::vector<LoggedRtcpPacketExtendedReports>* xr_list,
675 std::vector<LoggedRtcpPacketRemb>* remb_list,
676 std::vector<LoggedRtcpPacketNack>* nack_list,
677 std::vector<LoggedRtcpPacketFir>* fir_list,
678 std::vector<LoggedRtcpPacketPli>* pli_list,
679 std::vector<LoggedRtcpPacketTransportFeedback>* transport_feedback_list,
680 std::vector<LoggedRtcpPacketLossNotification>* loss_notification_list) {
681 rtcp::CommonHeader header;
682 for (const uint8_t* block = packet_begin; block < packet_end;
683 block = header.NextPacket()) {
684 RTC_PARSE_CHECK_OR_RETURN(header.Parse(block, packet_end - block));
685 if (header.type() == rtcp::TransportFeedback::kPacketType &&
686 header.fmt() == rtcp::TransportFeedback::kFeedbackMessageType) {
687 LoggedRtcpPacketTransportFeedback parsed_block;
688 parsed_block.timestamp_us = timestamp_us;
689 if (parsed_block.transport_feedback.Parse(header))
690 transport_feedback_list->push_back(std::move(parsed_block));
691 } else if (header.type() == rtcp::SenderReport::kPacketType) {
692 LoggedRtcpPacketSenderReport parsed_block;
693 parsed_block.timestamp_us = timestamp_us;
694 if (parsed_block.sr.Parse(header)) {
695 sr_list->push_back(std::move(parsed_block));
696 }
697 } else if (header.type() == rtcp::ReceiverReport::kPacketType) {
698 LoggedRtcpPacketReceiverReport parsed_block;
699 parsed_block.timestamp_us = timestamp_us;
700 if (parsed_block.rr.Parse(header)) {
701 rr_list->push_back(std::move(parsed_block));
702 }
703 } else if (header.type() == rtcp::ExtendedReports::kPacketType) {
704 LoggedRtcpPacketExtendedReports parsed_block;
705 parsed_block.timestamp_us = timestamp_us;
706 if (parsed_block.xr.Parse(header)) {
707 xr_list->push_back(std::move(parsed_block));
708 }
709 } else if (header.type() == rtcp::Fir::kPacketType &&
710 header.fmt() == rtcp::Fir::kFeedbackMessageType) {
711 LoggedRtcpPacketFir parsed_block;
712 parsed_block.timestamp_us = timestamp_us;
713 if (parsed_block.fir.Parse(header)) {
714 fir_list->push_back(std::move(parsed_block));
715 }
716 } else if (header.type() == rtcp::Pli::kPacketType &&
717 header.fmt() == rtcp::Pli::kFeedbackMessageType) {
718 LoggedRtcpPacketPli parsed_block;
719 parsed_block.timestamp_us = timestamp_us;
720 if (parsed_block.pli.Parse(header)) {
721 pli_list->push_back(std::move(parsed_block));
722 }
723 } else if (header.type() == rtcp::Remb::kPacketType &&
724 header.fmt() == rtcp::Psfb::kAfbMessageType) {
725 bool type_found = false;
726 if (!type_found) {
727 LoggedRtcpPacketRemb parsed_block;
728 parsed_block.timestamp_us = timestamp_us;
729 if (parsed_block.remb.Parse(header)) {
730 remb_list->push_back(std::move(parsed_block));
731 type_found = true;
732 }
733 }
734 if (!type_found) {
735 LoggedRtcpPacketLossNotification parsed_block;
736 parsed_block.timestamp_us = timestamp_us;
737 if (parsed_block.loss_notification.Parse(header)) {
738 loss_notification_list->push_back(std::move(parsed_block));
739 type_found = true;
740 }
741 }
742 } else if (header.type() == rtcp::Nack::kPacketType &&
743 header.fmt() == rtcp::Nack::kFeedbackMessageType) {
744 LoggedRtcpPacketNack parsed_block;
745 parsed_block.timestamp_us = timestamp_us;
746 if (parsed_block.nack.Parse(header)) {
747 nack_list->push_back(std::move(parsed_block));
748 }
749 }
750 }
751 return ParsedRtcEventLog::ParseStatus::Success();
752 }
753
754 } // namespace
755
756 // Conversion functions for version 2 of the wire format.
GetRuntimeDetectorState(rtclog2::DelayBasedBweUpdates::DetectorState detector_state)757 BandwidthUsage GetRuntimeDetectorState(
758 rtclog2::DelayBasedBweUpdates::DetectorState detector_state) {
759 switch (detector_state) {
760 case rtclog2::DelayBasedBweUpdates::BWE_NORMAL:
761 return BandwidthUsage::kBwNormal;
762 case rtclog2::DelayBasedBweUpdates::BWE_UNDERUSING:
763 return BandwidthUsage::kBwUnderusing;
764 case rtclog2::DelayBasedBweUpdates::BWE_OVERUSING:
765 return BandwidthUsage::kBwOverusing;
766 case rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE:
767 break;
768 }
769 RTC_NOTREACHED();
770 return BandwidthUsage::kBwNormal;
771 }
772
GetRuntimeProbeFailureReason(rtclog2::BweProbeResultFailure::FailureReason failure)773 ProbeFailureReason GetRuntimeProbeFailureReason(
774 rtclog2::BweProbeResultFailure::FailureReason failure) {
775 switch (failure) {
776 case rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_INTERVAL:
777 return ProbeFailureReason::kInvalidSendReceiveInterval;
778 case rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_RATIO:
779 return ProbeFailureReason::kInvalidSendReceiveRatio;
780 case rtclog2::BweProbeResultFailure::TIMEOUT:
781 return ProbeFailureReason::kTimeout;
782 case rtclog2::BweProbeResultFailure::UNKNOWN:
783 break;
784 }
785 RTC_NOTREACHED();
786 return ProbeFailureReason::kTimeout;
787 }
788
GetRuntimeDtlsTransportState(rtclog2::DtlsTransportStateEvent::DtlsTransportState state)789 DtlsTransportState GetRuntimeDtlsTransportState(
790 rtclog2::DtlsTransportStateEvent::DtlsTransportState state) {
791 switch (state) {
792 case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_NEW:
793 return DtlsTransportState::kNew;
794 case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTING:
795 return DtlsTransportState::kConnecting;
796 case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTED:
797 return DtlsTransportState::kConnected;
798 case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CLOSED:
799 return DtlsTransportState::kClosed;
800 case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_FAILED:
801 return DtlsTransportState::kFailed;
802 case rtclog2::DtlsTransportStateEvent::UNKNOWN_DTLS_TRANSPORT_STATE:
803 RTC_NOTREACHED();
804 return DtlsTransportState::kNumValues;
805 }
806 RTC_NOTREACHED();
807 return DtlsTransportState::kNumValues;
808 }
809
GetRuntimeIceCandidatePairConfigType(rtclog2::IceCandidatePairConfig::IceCandidatePairConfigType type)810 IceCandidatePairConfigType GetRuntimeIceCandidatePairConfigType(
811 rtclog2::IceCandidatePairConfig::IceCandidatePairConfigType type) {
812 switch (type) {
813 case rtclog2::IceCandidatePairConfig::ADDED:
814 return IceCandidatePairConfigType::kAdded;
815 case rtclog2::IceCandidatePairConfig::UPDATED:
816 return IceCandidatePairConfigType::kUpdated;
817 case rtclog2::IceCandidatePairConfig::DESTROYED:
818 return IceCandidatePairConfigType::kDestroyed;
819 case rtclog2::IceCandidatePairConfig::SELECTED:
820 return IceCandidatePairConfigType::kSelected;
821 case rtclog2::IceCandidatePairConfig::UNKNOWN_CONFIG_TYPE:
822 break;
823 }
824 RTC_NOTREACHED();
825 return IceCandidatePairConfigType::kAdded;
826 }
827
GetRuntimeIceCandidateType(rtclog2::IceCandidatePairConfig::IceCandidateType type)828 IceCandidateType GetRuntimeIceCandidateType(
829 rtclog2::IceCandidatePairConfig::IceCandidateType type) {
830 switch (type) {
831 case rtclog2::IceCandidatePairConfig::LOCAL:
832 return IceCandidateType::kLocal;
833 case rtclog2::IceCandidatePairConfig::STUN:
834 return IceCandidateType::kStun;
835 case rtclog2::IceCandidatePairConfig::PRFLX:
836 return IceCandidateType::kPrflx;
837 case rtclog2::IceCandidatePairConfig::RELAY:
838 return IceCandidateType::kRelay;
839 case rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
840 return IceCandidateType::kUnknown;
841 }
842 RTC_NOTREACHED();
843 return IceCandidateType::kUnknown;
844 }
845
GetRuntimeIceCandidatePairProtocol(rtclog2::IceCandidatePairConfig::Protocol protocol)846 IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
847 rtclog2::IceCandidatePairConfig::Protocol protocol) {
848 switch (protocol) {
849 case rtclog2::IceCandidatePairConfig::UDP:
850 return IceCandidatePairProtocol::kUdp;
851 case rtclog2::IceCandidatePairConfig::TCP:
852 return IceCandidatePairProtocol::kTcp;
853 case rtclog2::IceCandidatePairConfig::SSLTCP:
854 return IceCandidatePairProtocol::kSsltcp;
855 case rtclog2::IceCandidatePairConfig::TLS:
856 return IceCandidatePairProtocol::kTls;
857 case rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL:
858 return IceCandidatePairProtocol::kUnknown;
859 }
860 RTC_NOTREACHED();
861 return IceCandidatePairProtocol::kUnknown;
862 }
863
GetRuntimeIceCandidatePairAddressFamily(rtclog2::IceCandidatePairConfig::AddressFamily address_family)864 IceCandidatePairAddressFamily GetRuntimeIceCandidatePairAddressFamily(
865 rtclog2::IceCandidatePairConfig::AddressFamily address_family) {
866 switch (address_family) {
867 case rtclog2::IceCandidatePairConfig::IPV4:
868 return IceCandidatePairAddressFamily::kIpv4;
869 case rtclog2::IceCandidatePairConfig::IPV6:
870 return IceCandidatePairAddressFamily::kIpv6;
871 case rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY:
872 return IceCandidatePairAddressFamily::kUnknown;
873 }
874 RTC_NOTREACHED();
875 return IceCandidatePairAddressFamily::kUnknown;
876 }
877
GetRuntimeIceCandidateNetworkType(rtclog2::IceCandidatePairConfig::NetworkType network_type)878 IceCandidateNetworkType GetRuntimeIceCandidateNetworkType(
879 rtclog2::IceCandidatePairConfig::NetworkType network_type) {
880 switch (network_type) {
881 case rtclog2::IceCandidatePairConfig::ETHERNET:
882 return IceCandidateNetworkType::kEthernet;
883 case rtclog2::IceCandidatePairConfig::LOOPBACK:
884 return IceCandidateNetworkType::kLoopback;
885 case rtclog2::IceCandidatePairConfig::WIFI:
886 return IceCandidateNetworkType::kWifi;
887 case rtclog2::IceCandidatePairConfig::VPN:
888 return IceCandidateNetworkType::kVpn;
889 case rtclog2::IceCandidatePairConfig::CELLULAR:
890 return IceCandidateNetworkType::kCellular;
891 case rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE:
892 return IceCandidateNetworkType::kUnknown;
893 }
894 RTC_NOTREACHED();
895 return IceCandidateNetworkType::kUnknown;
896 }
897
GetRuntimeIceCandidatePairEventType(rtclog2::IceCandidatePairEvent::IceCandidatePairEventType type)898 IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
899 rtclog2::IceCandidatePairEvent::IceCandidatePairEventType type) {
900 switch (type) {
901 case rtclog2::IceCandidatePairEvent::CHECK_SENT:
902 return IceCandidatePairEventType::kCheckSent;
903 case rtclog2::IceCandidatePairEvent::CHECK_RECEIVED:
904 return IceCandidatePairEventType::kCheckReceived;
905 case rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_SENT:
906 return IceCandidatePairEventType::kCheckResponseSent;
907 case rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED:
908 return IceCandidatePairEventType::kCheckResponseReceived;
909 case rtclog2::IceCandidatePairEvent::UNKNOWN_CHECK_TYPE:
910 break;
911 }
912 RTC_NOTREACHED();
913 return IceCandidatePairEventType::kCheckSent;
914 }
915
GetRuntimeRtpHeaderExtensionConfig(const rtclog2::RtpHeaderExtensionConfig & proto_header_extensions)916 std::vector<RtpExtension> GetRuntimeRtpHeaderExtensionConfig(
917 const rtclog2::RtpHeaderExtensionConfig& proto_header_extensions) {
918 std::vector<RtpExtension> rtp_extensions;
919 if (proto_header_extensions.has_transmission_time_offset_id()) {
920 rtp_extensions.emplace_back(
921 RtpExtension::kTimestampOffsetUri,
922 proto_header_extensions.transmission_time_offset_id());
923 }
924 if (proto_header_extensions.has_absolute_send_time_id()) {
925 rtp_extensions.emplace_back(
926 RtpExtension::kAbsSendTimeUri,
927 proto_header_extensions.absolute_send_time_id());
928 }
929 if (proto_header_extensions.has_transport_sequence_number_id()) {
930 rtp_extensions.emplace_back(
931 RtpExtension::kTransportSequenceNumberUri,
932 proto_header_extensions.transport_sequence_number_id());
933 }
934 if (proto_header_extensions.has_audio_level_id()) {
935 rtp_extensions.emplace_back(RtpExtension::kAudioLevelUri,
936 proto_header_extensions.audio_level_id());
937 }
938 if (proto_header_extensions.has_video_rotation_id()) {
939 rtp_extensions.emplace_back(RtpExtension::kVideoRotationUri,
940 proto_header_extensions.video_rotation_id());
941 }
942 return rtp_extensions;
943 }
944 // End of conversion functions.
945
946 ParsedRtcEventLog::~ParsedRtcEventLog() = default;
947
948 ParsedRtcEventLog::LoggedRtpStreamIncoming::LoggedRtpStreamIncoming() = default;
949 ParsedRtcEventLog::LoggedRtpStreamIncoming::LoggedRtpStreamIncoming(
950 const LoggedRtpStreamIncoming& rhs) = default;
951 ParsedRtcEventLog::LoggedRtpStreamIncoming::~LoggedRtpStreamIncoming() =
952 default;
953
954 ParsedRtcEventLog::LoggedRtpStreamOutgoing::LoggedRtpStreamOutgoing() = default;
955 ParsedRtcEventLog::LoggedRtpStreamOutgoing::LoggedRtpStreamOutgoing(
956 const LoggedRtpStreamOutgoing& rhs) = default;
957 ParsedRtcEventLog::LoggedRtpStreamOutgoing::~LoggedRtpStreamOutgoing() =
958 default;
959
LoggedRtpStreamView(uint32_t ssrc,const LoggedRtpPacketIncoming * ptr,size_t num_elements)960 ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
961 uint32_t ssrc,
962 const LoggedRtpPacketIncoming* ptr,
963 size_t num_elements)
964 : ssrc(ssrc),
965 packet_view(PacketView<const LoggedRtpPacket>::Create(
966 ptr,
967 num_elements,
968 offsetof(LoggedRtpPacketIncoming, rtp))) {}
969
LoggedRtpStreamView(uint32_t ssrc,const LoggedRtpPacketOutgoing * ptr,size_t num_elements)970 ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
971 uint32_t ssrc,
972 const LoggedRtpPacketOutgoing* ptr,
973 size_t num_elements)
974 : ssrc(ssrc),
975 packet_view(PacketView<const LoggedRtpPacket>::Create(
976 ptr,
977 num_elements,
978 offsetof(LoggedRtpPacketOutgoing, rtp))) {}
979
980 ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
981 const LoggedRtpStreamView&) = default;
982
983 // Return default values for header extensions, to use on streams without stored
984 // mapping data. Currently this only applies to audio streams, since the mapping
985 // is not stored in the event log.
986 // TODO(ivoc): Remove this once this mapping is stored in the event log for
987 // audio streams. Tracking bug: webrtc:6399
988 webrtc::RtpHeaderExtensionMap
GetDefaultHeaderExtensionMap()989 ParsedRtcEventLog::GetDefaultHeaderExtensionMap() {
990 // Values from before the default RTP header extension IDs were removed.
991 constexpr int kAudioLevelDefaultId = 1;
992 constexpr int kTimestampOffsetDefaultId = 2;
993 constexpr int kAbsSendTimeDefaultId = 3;
994 constexpr int kVideoRotationDefaultId = 4;
995 constexpr int kTransportSequenceNumberDefaultId = 5;
996 constexpr int kPlayoutDelayDefaultId = 6;
997 constexpr int kVideoContentTypeDefaultId = 7;
998 constexpr int kVideoTimingDefaultId = 8;
999
1000 webrtc::RtpHeaderExtensionMap default_map;
1001 default_map.Register<AudioLevel>(kAudioLevelDefaultId);
1002 default_map.Register<TransmissionOffset>(kTimestampOffsetDefaultId);
1003 default_map.Register<AbsoluteSendTime>(kAbsSendTimeDefaultId);
1004 default_map.Register<VideoOrientation>(kVideoRotationDefaultId);
1005 default_map.Register<TransportSequenceNumber>(
1006 kTransportSequenceNumberDefaultId);
1007 default_map.Register<PlayoutDelayLimits>(kPlayoutDelayDefaultId);
1008 default_map.Register<VideoContentTypeExtension>(kVideoContentTypeDefaultId);
1009 default_map.Register<VideoTimingExtension>(kVideoTimingDefaultId);
1010 return default_map;
1011 }
1012
ParsedRtcEventLog(UnconfiguredHeaderExtensions parse_unconfigured_header_extensions,bool allow_incomplete_logs)1013 ParsedRtcEventLog::ParsedRtcEventLog(
1014 UnconfiguredHeaderExtensions parse_unconfigured_header_extensions,
1015 bool allow_incomplete_logs)
1016 : parse_unconfigured_header_extensions_(
1017 parse_unconfigured_header_extensions),
1018 allow_incomplete_logs_(allow_incomplete_logs) {
1019 Clear();
1020 }
1021
Clear()1022 void ParsedRtcEventLog::Clear() {
1023 default_extension_map_ = GetDefaultHeaderExtensionMap();
1024
1025 incoming_rtx_ssrcs_.clear();
1026 incoming_video_ssrcs_.clear();
1027 incoming_audio_ssrcs_.clear();
1028 outgoing_rtx_ssrcs_.clear();
1029 outgoing_video_ssrcs_.clear();
1030 outgoing_audio_ssrcs_.clear();
1031
1032 incoming_rtp_packets_map_.clear();
1033 outgoing_rtp_packets_map_.clear();
1034 incoming_rtp_packets_by_ssrc_.clear();
1035 outgoing_rtp_packets_by_ssrc_.clear();
1036 incoming_rtp_packet_views_by_ssrc_.clear();
1037 outgoing_rtp_packet_views_by_ssrc_.clear();
1038
1039 incoming_rtcp_packets_.clear();
1040 outgoing_rtcp_packets_.clear();
1041
1042 incoming_rr_.clear();
1043 outgoing_rr_.clear();
1044 incoming_sr_.clear();
1045 outgoing_sr_.clear();
1046 incoming_nack_.clear();
1047 outgoing_nack_.clear();
1048 incoming_remb_.clear();
1049 outgoing_remb_.clear();
1050 incoming_transport_feedback_.clear();
1051 outgoing_transport_feedback_.clear();
1052 incoming_loss_notification_.clear();
1053 outgoing_loss_notification_.clear();
1054
1055 start_log_events_.clear();
1056 stop_log_events_.clear();
1057 audio_playout_events_.clear();
1058 audio_network_adaptation_events_.clear();
1059 bwe_probe_cluster_created_events_.clear();
1060 bwe_probe_failure_events_.clear();
1061 bwe_probe_success_events_.clear();
1062 bwe_delay_updates_.clear();
1063 bwe_loss_updates_.clear();
1064 dtls_transport_states_.clear();
1065 dtls_writable_states_.clear();
1066 alr_state_events_.clear();
1067 ice_candidate_pair_configs_.clear();
1068 ice_candidate_pair_events_.clear();
1069 audio_recv_configs_.clear();
1070 audio_send_configs_.clear();
1071 video_recv_configs_.clear();
1072 video_send_configs_.clear();
1073
1074 memset(last_incoming_rtcp_packet_, 0, IP_PACKET_SIZE);
1075 last_incoming_rtcp_packet_length_ = 0;
1076
1077 first_timestamp_ = std::numeric_limits<int64_t>::max();
1078 last_timestamp_ = std::numeric_limits<int64_t>::min();
1079 first_log_segment_ = LogSegment(0, std::numeric_limits<int64_t>::max());
1080
1081 incoming_rtp_extensions_maps_.clear();
1082 outgoing_rtp_extensions_maps_.clear();
1083 }
1084
ParseFile(const std::string & filename)1085 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseFile(
1086 const std::string& filename) {
1087 std::ifstream file( // no-presubmit-check TODO(webrtc:8982)
1088 filename, std::ios_base::in | std::ios_base::binary);
1089 if (!file.good() || !file.is_open()) {
1090 RTC_LOG(LS_WARNING) << "Could not open file for reading.";
1091 RTC_PARSE_CHECK_OR_RETURN(file.good() && file.is_open());
1092 }
1093
1094 return ParseStream(file);
1095 }
1096
ParseString(const std::string & s)1097 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseString(
1098 const std::string& s) {
1099 std::istringstream stream( // no-presubmit-check TODO(webrtc:8982)
1100 s, std::ios_base::in | std::ios_base::binary);
1101 return ParseStream(stream);
1102 }
1103
ParseStream(std::istream & stream)1104 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
1105 std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
1106 Clear();
1107 ParseStatus status = ParseStreamInternal(stream);
1108
1109 // Cache the configured SSRCs.
1110 for (const auto& video_recv_config : video_recv_configs()) {
1111 incoming_video_ssrcs_.insert(video_recv_config.config.remote_ssrc);
1112 incoming_video_ssrcs_.insert(video_recv_config.config.rtx_ssrc);
1113 incoming_rtx_ssrcs_.insert(video_recv_config.config.rtx_ssrc);
1114 }
1115 for (const auto& video_send_config : video_send_configs()) {
1116 outgoing_video_ssrcs_.insert(video_send_config.config.local_ssrc);
1117 outgoing_video_ssrcs_.insert(video_send_config.config.rtx_ssrc);
1118 outgoing_rtx_ssrcs_.insert(video_send_config.config.rtx_ssrc);
1119 }
1120 for (const auto& audio_recv_config : audio_recv_configs()) {
1121 incoming_audio_ssrcs_.insert(audio_recv_config.config.remote_ssrc);
1122 }
1123 for (const auto& audio_send_config : audio_send_configs()) {
1124 outgoing_audio_ssrcs_.insert(audio_send_config.config.local_ssrc);
1125 }
1126
1127 // ParseStreamInternal stores the RTP packets in a map indexed by SSRC.
1128 // Since we dont need rapid lookup based on SSRC after parsing, we move the
1129 // packets_streams from map to vector.
1130 incoming_rtp_packets_by_ssrc_.reserve(incoming_rtp_packets_map_.size());
1131 for (auto& kv : incoming_rtp_packets_map_) {
1132 incoming_rtp_packets_by_ssrc_.emplace_back(LoggedRtpStreamIncoming());
1133 incoming_rtp_packets_by_ssrc_.back().ssrc = kv.first;
1134 incoming_rtp_packets_by_ssrc_.back().incoming_packets =
1135 std::move(kv.second);
1136 }
1137 incoming_rtp_packets_map_.clear();
1138 outgoing_rtp_packets_by_ssrc_.reserve(outgoing_rtp_packets_map_.size());
1139 for (auto& kv : outgoing_rtp_packets_map_) {
1140 outgoing_rtp_packets_by_ssrc_.emplace_back(LoggedRtpStreamOutgoing());
1141 outgoing_rtp_packets_by_ssrc_.back().ssrc = kv.first;
1142 outgoing_rtp_packets_by_ssrc_.back().outgoing_packets =
1143 std::move(kv.second);
1144 }
1145 outgoing_rtp_packets_map_.clear();
1146
1147 // Build PacketViews for easier iteration over RTP packets.
1148 for (const auto& stream : incoming_rtp_packets_by_ssrc_) {
1149 incoming_rtp_packet_views_by_ssrc_.emplace_back(
1150 LoggedRtpStreamView(stream.ssrc, stream.incoming_packets.data(),
1151 stream.incoming_packets.size()));
1152 }
1153 for (const auto& stream : outgoing_rtp_packets_by_ssrc_) {
1154 outgoing_rtp_packet_views_by_ssrc_.emplace_back(
1155 LoggedRtpStreamView(stream.ssrc, stream.outgoing_packets.data(),
1156 stream.outgoing_packets.size()));
1157 }
1158
1159 // Set up convenience wrappers around the most commonly used RTCP types.
1160 for (const auto& incoming : incoming_rtcp_packets_) {
1161 const int64_t timestamp_us = incoming.rtcp.timestamp_us;
1162 const uint8_t* packet_begin = incoming.rtcp.raw_data.data();
1163 const uint8_t* packet_end = packet_begin + incoming.rtcp.raw_data.size();
1164 auto status = StoreRtcpBlocks(
1165 timestamp_us, packet_begin, packet_end, &incoming_sr_, &incoming_rr_,
1166 &incoming_xr_, &incoming_remb_, &incoming_nack_, &incoming_fir_,
1167 &incoming_pli_, &incoming_transport_feedback_,
1168 &incoming_loss_notification_);
1169 RTC_RETURN_IF_ERROR(status);
1170 }
1171
1172 for (const auto& outgoing : outgoing_rtcp_packets_) {
1173 const int64_t timestamp_us = outgoing.rtcp.timestamp_us;
1174 const uint8_t* packet_begin = outgoing.rtcp.raw_data.data();
1175 const uint8_t* packet_end = packet_begin + outgoing.rtcp.raw_data.size();
1176 auto status = StoreRtcpBlocks(
1177 timestamp_us, packet_begin, packet_end, &outgoing_sr_, &outgoing_rr_,
1178 &outgoing_xr_, &outgoing_remb_, &outgoing_nack_, &outgoing_fir_,
1179 &outgoing_pli_, &outgoing_transport_feedback_,
1180 &outgoing_loss_notification_);
1181 RTC_RETURN_IF_ERROR(status);
1182 }
1183
1184 // Store first and last timestamp events that might happen before the call is
1185 // connected or after the call is disconnected. Typical examples are
1186 // stream configurations and starting/stopping the log.
1187 // TODO(terelius): Figure out if we actually need to find the first and last
1188 // timestamp in the parser. It seems like this could be done by the caller.
1189 first_timestamp_ = std::numeric_limits<int64_t>::max();
1190 last_timestamp_ = std::numeric_limits<int64_t>::min();
1191 StoreFirstAndLastTimestamp(alr_state_events());
1192 StoreFirstAndLastTimestamp(route_change_events());
1193 for (const auto& audio_stream : audio_playout_events()) {
1194 // Audio playout events are grouped by SSRC.
1195 StoreFirstAndLastTimestamp(audio_stream.second);
1196 }
1197 StoreFirstAndLastTimestamp(audio_network_adaptation_events());
1198 StoreFirstAndLastTimestamp(bwe_probe_cluster_created_events());
1199 StoreFirstAndLastTimestamp(bwe_probe_failure_events());
1200 StoreFirstAndLastTimestamp(bwe_probe_success_events());
1201 StoreFirstAndLastTimestamp(bwe_delay_updates());
1202 StoreFirstAndLastTimestamp(bwe_loss_updates());
1203 StoreFirstAndLastTimestamp(dtls_transport_states());
1204 StoreFirstAndLastTimestamp(dtls_writable_states());
1205 StoreFirstAndLastTimestamp(ice_candidate_pair_configs());
1206 StoreFirstAndLastTimestamp(ice_candidate_pair_events());
1207 for (const auto& rtp_stream : incoming_rtp_packets_by_ssrc()) {
1208 StoreFirstAndLastTimestamp(rtp_stream.incoming_packets);
1209 }
1210 for (const auto& rtp_stream : outgoing_rtp_packets_by_ssrc()) {
1211 StoreFirstAndLastTimestamp(rtp_stream.outgoing_packets);
1212 }
1213 StoreFirstAndLastTimestamp(incoming_rtcp_packets());
1214 StoreFirstAndLastTimestamp(outgoing_rtcp_packets());
1215 StoreFirstAndLastTimestamp(generic_packets_sent_);
1216 StoreFirstAndLastTimestamp(generic_packets_received_);
1217 StoreFirstAndLastTimestamp(generic_acks_received_);
1218 StoreFirstAndLastTimestamp(remote_estimate_events_);
1219
1220 // Stop events could be missing due to file size limits. If so, use the
1221 // last event, or the next start timestamp if available.
1222 // TODO(terelius): This could be improved. Instead of using the next start
1223 // event, we could use the timestamp of the the last previous regular event.
1224 auto start_iter = start_log_events().begin();
1225 auto stop_iter = stop_log_events().begin();
1226 int64_t start_us = first_timestamp();
1227 int64_t next_start_us = std::numeric_limits<int64_t>::max();
1228 int64_t stop_us = std::numeric_limits<int64_t>::max();
1229 if (start_iter != start_log_events().end()) {
1230 start_us = std::min(start_us, start_iter->log_time_us());
1231 ++start_iter;
1232 if (start_iter != start_log_events().end())
1233 next_start_us = start_iter->log_time_us();
1234 }
1235 if (stop_iter != stop_log_events().end()) {
1236 stop_us = stop_iter->log_time_us();
1237 }
1238 stop_us = std::min(stop_us, next_start_us);
1239 if (stop_us == std::numeric_limits<int64_t>::max() &&
1240 last_timestamp() != std::numeric_limits<int64_t>::min()) {
1241 stop_us = last_timestamp();
1242 }
1243 RTC_PARSE_CHECK_OR_RETURN_LE(start_us, stop_us);
1244 first_log_segment_ = LogSegment(start_us, stop_us);
1245
1246 if (first_timestamp_ == std::numeric_limits<int64_t>::max() &&
1247 last_timestamp_ == std::numeric_limits<int64_t>::min()) {
1248 first_timestamp_ = last_timestamp_ = 0;
1249 }
1250
1251 return status;
1252 }
1253
ParseStreamInternal(std::istream & stream)1254 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternal(
1255 std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
1256 constexpr uint64_t kMaxEventSize = 10000000; // Sanity check.
1257 std::vector<char> buffer(0xFFFF);
1258
1259 RTC_DCHECK(stream.good());
1260 while (1) {
1261 // Check whether we have reached end of file.
1262 stream.peek();
1263 if (stream.eof()) {
1264 break;
1265 }
1266
1267 // Read the next message tag. Protobuf defines the message tag as
1268 // (field_number << 3) | wire_type. In the legacy encoding, the field number
1269 // is supposed to be 1 and the wire type for a length-delimited field is 2.
1270 // In the new encoding we still expect the wire type to be 2, but the field
1271 // number will be greater than 1.
1272 constexpr uint64_t kExpectedV1Tag = (1 << 3) | 2;
1273 size_t bytes_written = 0;
1274 ParsedRtcEventLog::ParseStatusOr<uint64_t> tag =
1275 ParseVarInt(stream, buffer.data(), &bytes_written);
1276 if (!tag.ok()) {
1277 RTC_LOG(LS_WARNING)
1278 << "Missing field tag from beginning of protobuf event.";
1279 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1280 kIncompleteLogError);
1281 return tag.status();
1282 }
1283 constexpr uint64_t kWireTypeMask = 0x07;
1284 const uint64_t wire_type = tag.value() & kWireTypeMask;
1285 if (wire_type != 2) {
1286 RTC_LOG(LS_WARNING) << "Expected field tag with wire type 2 (length "
1287 "delimited message). Found wire type "
1288 << wire_type;
1289 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1290 kIncompleteLogError);
1291 RTC_PARSE_CHECK_OR_RETURN_EQ(wire_type, 2);
1292 }
1293
1294 // Read the length field.
1295 ParsedRtcEventLog::ParseStatusOr<uint64_t> message_length =
1296 ParseVarInt(stream, buffer.data(), &bytes_written);
1297 if (!message_length.ok()) {
1298 RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
1299 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1300 kIncompleteLogError);
1301 return message_length.status();
1302 } else if (message_length.value() > kMaxEventSize) {
1303 RTC_LOG(LS_WARNING) << "Protobuf message length is too large.";
1304 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1305 kIncompleteLogError);
1306 RTC_PARSE_CHECK_OR_RETURN_LE(message_length.value(), kMaxEventSize);
1307 }
1308
1309 // Read the next protobuf event to a temporary char buffer.
1310 if (buffer.size() < bytes_written + message_length.value())
1311 buffer.resize(bytes_written + message_length.value());
1312 stream.read(buffer.data() + bytes_written, message_length.value());
1313 if (stream.gcount() != static_cast<int>(message_length.value())) {
1314 RTC_LOG(LS_WARNING) << "Failed to read protobuf message.";
1315 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1316 kIncompleteLogError);
1317 RTC_PARSE_CHECK_OR_RETURN(false);
1318 }
1319 size_t buffer_size = bytes_written + message_length.value();
1320
1321 if (tag.value() == kExpectedV1Tag) {
1322 // Parse the protobuf event from the buffer.
1323 rtclog::EventStream event_stream;
1324 if (!event_stream.ParseFromArray(buffer.data(), buffer_size)) {
1325 RTC_LOG(LS_WARNING)
1326 << "Failed to parse legacy-format protobuf message.";
1327 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1328 kIncompleteLogError);
1329 RTC_PARSE_CHECK_OR_RETURN(false);
1330 }
1331
1332 RTC_PARSE_CHECK_OR_RETURN_EQ(event_stream.stream_size(), 1);
1333 auto status = StoreParsedLegacyEvent(event_stream.stream(0));
1334 RTC_RETURN_IF_ERROR(status);
1335 } else {
1336 // Parse the protobuf event from the buffer.
1337 rtclog2::EventStream event_stream;
1338 if (!event_stream.ParseFromArray(buffer.data(), buffer_size)) {
1339 RTC_LOG(LS_WARNING) << "Failed to parse new-format protobuf message.";
1340 RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
1341 kIncompleteLogError);
1342 RTC_PARSE_CHECK_OR_RETURN(false);
1343 }
1344 auto status = StoreParsedNewFormatEvent(event_stream);
1345 RTC_RETURN_IF_ERROR(status);
1346 }
1347 }
1348 return ParseStatus::Success();
1349 }
1350
1351 template <typename T>
StoreFirstAndLastTimestamp(const std::vector<T> & v)1352 void ParsedRtcEventLog::StoreFirstAndLastTimestamp(const std::vector<T>& v) {
1353 if (v.empty())
1354 return;
1355 first_timestamp_ = std::min(first_timestamp_, v.front().log_time_us());
1356 last_timestamp_ = std::max(last_timestamp_, v.back().log_time_us());
1357 }
1358
StoreParsedLegacyEvent(const rtclog::Event & event)1359 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
1360 const rtclog::Event& event) {
1361 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1362 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1363 switch (event.type()) {
1364 case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT: {
1365 auto config = GetVideoReceiveConfig(event);
1366 if (!config.ok())
1367 return config.status();
1368
1369 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1370 int64_t timestamp_us = event.timestamp_us();
1371 video_recv_configs_.emplace_back(timestamp_us, config.value());
1372 incoming_rtp_extensions_maps_[config.value().remote_ssrc] =
1373 RtpHeaderExtensionMap(config.value().rtp_extensions);
1374 incoming_rtp_extensions_maps_[config.value().rtx_ssrc] =
1375 RtpHeaderExtensionMap(config.value().rtp_extensions);
1376 break;
1377 }
1378 case rtclog::Event::VIDEO_SENDER_CONFIG_EVENT: {
1379 auto config = GetVideoSendConfig(event);
1380 if (!config.ok())
1381 return config.status();
1382
1383 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1384 int64_t timestamp_us = event.timestamp_us();
1385 video_send_configs_.emplace_back(timestamp_us, config.value());
1386 outgoing_rtp_extensions_maps_[config.value().local_ssrc] =
1387 RtpHeaderExtensionMap(config.value().rtp_extensions);
1388 outgoing_rtp_extensions_maps_[config.value().rtx_ssrc] =
1389 RtpHeaderExtensionMap(config.value().rtp_extensions);
1390 break;
1391 }
1392 case rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT: {
1393 auto config = GetAudioReceiveConfig(event);
1394 if (!config.ok())
1395 return config.status();
1396
1397 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1398 int64_t timestamp_us = event.timestamp_us();
1399 audio_recv_configs_.emplace_back(timestamp_us, config.value());
1400 incoming_rtp_extensions_maps_[config.value().remote_ssrc] =
1401 RtpHeaderExtensionMap(config.value().rtp_extensions);
1402 break;
1403 }
1404 case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT: {
1405 auto config = GetAudioSendConfig(event);
1406 if (!config.ok())
1407 return config.status();
1408 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1409 int64_t timestamp_us = event.timestamp_us();
1410 audio_send_configs_.emplace_back(timestamp_us, config.value());
1411 outgoing_rtp_extensions_maps_[config.value().local_ssrc] =
1412 RtpHeaderExtensionMap(config.value().rtp_extensions);
1413 break;
1414 }
1415 case rtclog::Event::RTP_EVENT: {
1416 PacketDirection direction;
1417 uint8_t header[IP_PACKET_SIZE];
1418 size_t header_length;
1419 size_t total_length;
1420 ParseStatus status = GetRtpHeader(event, &direction, header,
1421 &header_length, &total_length, nullptr);
1422 RTC_RETURN_IF_ERROR(status);
1423
1424 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(header + 8);
1425 const RtpHeaderExtensionMap* extension_map =
1426 GetRtpHeaderExtensionMap(direction, ssrc);
1427 RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
1428 RTPHeader parsed_header;
1429 rtp_parser.Parse(&parsed_header, extension_map, /*header_only*/ true);
1430
1431 // Since we give the parser only a header, there is no way for it to know
1432 // the padding length. The best solution would be to log the padding
1433 // length in RTC event log. In absence of it, we assume the RTP packet to
1434 // contain only padding, if the padding bit is set.
1435 // TODO(webrtc:9730): Use a generic way to obtain padding length.
1436 if ((header[0] & 0x20) != 0)
1437 parsed_header.paddingLength = total_length - header_length;
1438
1439 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1440 int64_t timestamp_us = event.timestamp_us();
1441 if (direction == kIncomingPacket) {
1442 incoming_rtp_packets_map_[parsed_header.ssrc].push_back(
1443 LoggedRtpPacketIncoming(timestamp_us, parsed_header, header_length,
1444 total_length));
1445 } else {
1446 outgoing_rtp_packets_map_[parsed_header.ssrc].push_back(
1447 LoggedRtpPacketOutgoing(timestamp_us, parsed_header, header_length,
1448 total_length));
1449 }
1450 break;
1451 }
1452 case rtclog::Event::RTCP_EVENT: {
1453 PacketDirection direction;
1454 uint8_t packet[IP_PACKET_SIZE];
1455 size_t total_length;
1456 auto status = GetRtcpPacket(event, &direction, packet, &total_length);
1457 RTC_RETURN_IF_ERROR(status);
1458 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1459 int64_t timestamp_us = event.timestamp_us();
1460 RTC_PARSE_CHECK_OR_RETURN_LE(total_length, IP_PACKET_SIZE);
1461 if (direction == kIncomingPacket) {
1462 // Currently incoming RTCP packets are logged twice, both for audio and
1463 // video. Only act on one of them. Compare against the previous parsed
1464 // incoming RTCP packet.
1465 if (total_length == last_incoming_rtcp_packet_length_ &&
1466 memcmp(last_incoming_rtcp_packet_, packet, total_length) == 0)
1467 break;
1468 incoming_rtcp_packets_.push_back(
1469 LoggedRtcpPacketIncoming(timestamp_us, packet, total_length));
1470 last_incoming_rtcp_packet_length_ = total_length;
1471 memcpy(last_incoming_rtcp_packet_, packet, total_length);
1472 } else {
1473 outgoing_rtcp_packets_.push_back(
1474 LoggedRtcpPacketOutgoing(timestamp_us, packet, total_length));
1475 }
1476 break;
1477 }
1478 case rtclog::Event::LOG_START: {
1479 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1480 int64_t timestamp_us = event.timestamp_us();
1481 start_log_events_.push_back(LoggedStartEvent(timestamp_us));
1482 break;
1483 }
1484 case rtclog::Event::LOG_END: {
1485 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1486 int64_t timestamp_us = event.timestamp_us();
1487 stop_log_events_.push_back(LoggedStopEvent(timestamp_us));
1488 break;
1489 }
1490 case rtclog::Event::AUDIO_PLAYOUT_EVENT: {
1491 auto status_or_value = GetAudioPlayout(event);
1492 RTC_RETURN_IF_ERROR(status_or_value.status());
1493 LoggedAudioPlayoutEvent playout_event = status_or_value.value();
1494 audio_playout_events_[playout_event.ssrc].push_back(playout_event);
1495 break;
1496 }
1497 case rtclog::Event::LOSS_BASED_BWE_UPDATE: {
1498 auto status_or_value = GetLossBasedBweUpdate(event);
1499 RTC_RETURN_IF_ERROR(status_or_value.status());
1500 bwe_loss_updates_.push_back(status_or_value.value());
1501 break;
1502 }
1503 case rtclog::Event::DELAY_BASED_BWE_UPDATE: {
1504 auto status_or_value = GetDelayBasedBweUpdate(event);
1505 RTC_RETURN_IF_ERROR(status_or_value.status());
1506 bwe_delay_updates_.push_back(status_or_value.value());
1507 break;
1508 }
1509 case rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT: {
1510 auto status_or_value = GetAudioNetworkAdaptation(event);
1511 RTC_RETURN_IF_ERROR(status_or_value.status());
1512 LoggedAudioNetworkAdaptationEvent ana_event = status_or_value.value();
1513 audio_network_adaptation_events_.push_back(ana_event);
1514 break;
1515 }
1516 case rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT: {
1517 auto status_or_value = GetBweProbeClusterCreated(event);
1518 RTC_RETURN_IF_ERROR(status_or_value.status());
1519 bwe_probe_cluster_created_events_.push_back(status_or_value.value());
1520 break;
1521 }
1522 case rtclog::Event::BWE_PROBE_RESULT_EVENT: {
1523 // Probe successes and failures are currently stored in the same proto
1524 // message, we are moving towards separate messages. Probe results
1525 // therefore need special treatment in the parser.
1526 RTC_PARSE_CHECK_OR_RETURN(event.has_probe_result());
1527 RTC_PARSE_CHECK_OR_RETURN(event.probe_result().has_result());
1528 if (event.probe_result().result() == rtclog::BweProbeResult::SUCCESS) {
1529 auto status_or_value = GetBweProbeSuccess(event);
1530 RTC_RETURN_IF_ERROR(status_or_value.status());
1531 bwe_probe_success_events_.push_back(status_or_value.value());
1532 } else {
1533 auto status_or_value = GetBweProbeFailure(event);
1534 RTC_RETURN_IF_ERROR(status_or_value.status());
1535 bwe_probe_failure_events_.push_back(status_or_value.value());
1536 }
1537 break;
1538 }
1539 case rtclog::Event::ALR_STATE_EVENT: {
1540 auto status_or_value = GetAlrState(event);
1541 RTC_RETURN_IF_ERROR(status_or_value.status());
1542 alr_state_events_.push_back(status_or_value.value());
1543 break;
1544 }
1545 case rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG: {
1546 auto status_or_value = GetIceCandidatePairConfig(event);
1547 RTC_RETURN_IF_ERROR(status_or_value.status());
1548 ice_candidate_pair_configs_.push_back(status_or_value.value());
1549 break;
1550 }
1551 case rtclog::Event::ICE_CANDIDATE_PAIR_EVENT: {
1552 auto status_or_value = GetIceCandidatePairEvent(event);
1553 RTC_RETURN_IF_ERROR(status_or_value.status());
1554 ice_candidate_pair_events_.push_back(status_or_value.value());
1555 break;
1556 }
1557 case rtclog::Event::UNKNOWN_EVENT: {
1558 break;
1559 }
1560 }
1561 return ParseStatus::Success();
1562 }
1563
1564 // The header must have space for at least IP_PACKET_SIZE bytes.
GetRtpHeader(const rtclog::Event & event,PacketDirection * incoming,uint8_t * header,size_t * header_length,size_t * total_length,int * probe_cluster_id) const1565 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::GetRtpHeader(
1566 const rtclog::Event& event,
1567 PacketDirection* incoming,
1568 uint8_t* header,
1569 size_t* header_length,
1570 size_t* total_length,
1571 int* probe_cluster_id) const {
1572 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1573 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::RTP_EVENT);
1574 RTC_PARSE_CHECK_OR_RETURN(event.has_rtp_packet());
1575 const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
1576 // Get direction of packet.
1577 RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_incoming());
1578 if (incoming != nullptr) {
1579 *incoming = rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
1580 }
1581 // Get packet length.
1582 RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_packet_length());
1583 if (total_length != nullptr) {
1584 *total_length = rtp_packet.packet_length();
1585 }
1586 // Get header length.
1587 RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_header());
1588 if (header_length != nullptr) {
1589 *header_length = rtp_packet.header().size();
1590 }
1591 if (probe_cluster_id != nullptr) {
1592 if (rtp_packet.has_probe_cluster_id()) {
1593 *probe_cluster_id = rtp_packet.probe_cluster_id();
1594 RTC_PARSE_CHECK_OR_RETURN_NE(*probe_cluster_id,
1595 PacedPacketInfo::kNotAProbe);
1596 } else {
1597 *probe_cluster_id = PacedPacketInfo::kNotAProbe;
1598 }
1599 }
1600 // Get header contents.
1601 if (header != nullptr) {
1602 const size_t kMinRtpHeaderSize = 12;
1603 RTC_PARSE_CHECK_OR_RETURN_GE(rtp_packet.header().size(), kMinRtpHeaderSize);
1604 RTC_PARSE_CHECK_OR_RETURN_LE(rtp_packet.header().size(),
1605 static_cast<size_t>(IP_PACKET_SIZE));
1606 memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
1607 }
1608 return ParseStatus::Success();
1609 }
1610
GetRtpHeaderExtensionMap(PacketDirection direction,uint32_t ssrc)1611 const RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeaderExtensionMap(
1612 PacketDirection direction,
1613 uint32_t ssrc) {
1614 auto& extensions_maps = direction == PacketDirection::kIncomingPacket
1615 ? incoming_rtp_extensions_maps_
1616 : outgoing_rtp_extensions_maps_;
1617 auto it = extensions_maps.find(ssrc);
1618 if (it != extensions_maps.end()) {
1619 return &(it->second);
1620 }
1621 if (parse_unconfigured_header_extensions_ ==
1622 UnconfiguredHeaderExtensions::kAttemptWebrtcDefaultConfig) {
1623 RTC_LOG(LS_WARNING) << "Using default header extension map for SSRC "
1624 << ssrc;
1625 extensions_maps.insert(std::make_pair(ssrc, default_extension_map_));
1626 return &default_extension_map_;
1627 }
1628 RTC_LOG(LS_WARNING) << "Not parsing header extensions for SSRC " << ssrc
1629 << ". No header extension map found.";
1630 return nullptr;
1631 }
1632
1633 // The packet must have space for at least IP_PACKET_SIZE bytes.
GetRtcpPacket(const rtclog::Event & event,PacketDirection * incoming,uint8_t * packet,size_t * length) const1634 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::GetRtcpPacket(
1635 const rtclog::Event& event,
1636 PacketDirection* incoming,
1637 uint8_t* packet,
1638 size_t* length) const {
1639 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1640 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::RTCP_EVENT);
1641 RTC_PARSE_CHECK_OR_RETURN(event.has_rtcp_packet());
1642 const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
1643 // Get direction of packet.
1644 RTC_PARSE_CHECK_OR_RETURN(rtcp_packet.has_incoming());
1645 if (incoming != nullptr) {
1646 *incoming = rtcp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
1647 }
1648 // Get packet length.
1649 RTC_PARSE_CHECK_OR_RETURN(rtcp_packet.has_packet_data());
1650 if (length != nullptr) {
1651 *length = rtcp_packet.packet_data().size();
1652 }
1653 // Get packet contents.
1654 if (packet != nullptr) {
1655 RTC_PARSE_CHECK_OR_RETURN_LE(rtcp_packet.packet_data().size(),
1656 static_cast<unsigned>(IP_PACKET_SIZE));
1657 memcpy(packet, rtcp_packet.packet_data().data(),
1658 rtcp_packet.packet_data().size());
1659 }
1660 return ParseStatus::Success();
1661 }
1662
1663 ParsedRtcEventLog::ParseStatusOr<rtclog::StreamConfig>
GetVideoReceiveConfig(const rtclog::Event & event) const1664 ParsedRtcEventLog::GetVideoReceiveConfig(const rtclog::Event& event) const {
1665 rtclog::StreamConfig config;
1666 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1667 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1668 rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
1669 RTC_PARSE_CHECK_OR_RETURN(event.has_video_receiver_config());
1670 const rtclog::VideoReceiveConfig& receiver_config =
1671 event.video_receiver_config();
1672 // Get SSRCs.
1673 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_remote_ssrc());
1674 config.remote_ssrc = receiver_config.remote_ssrc();
1675 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_local_ssrc());
1676 config.local_ssrc = receiver_config.local_ssrc();
1677 config.rtx_ssrc = 0;
1678 // Get RTCP settings.
1679 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_rtcp_mode());
1680 config.rtcp_mode = GetRuntimeRtcpMode(receiver_config.rtcp_mode());
1681 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_remb());
1682 config.remb = receiver_config.remb();
1683
1684 // Get RTX map.
1685 std::map<uint32_t, const rtclog::RtxConfig> rtx_map;
1686 for (int i = 0; i < receiver_config.rtx_map_size(); i++) {
1687 const rtclog::RtxMap& map = receiver_config.rtx_map(i);
1688 RTC_PARSE_CHECK_OR_RETURN(map.has_payload_type());
1689 RTC_PARSE_CHECK_OR_RETURN(map.has_config());
1690 RTC_PARSE_CHECK_OR_RETURN(map.config().has_rtx_ssrc());
1691 RTC_PARSE_CHECK_OR_RETURN(map.config().has_rtx_payload_type());
1692 rtx_map.insert(std::make_pair(map.payload_type(), map.config()));
1693 }
1694
1695 // Get header extensions.
1696 auto status = GetHeaderExtensions(&config.rtp_extensions,
1697 receiver_config.header_extensions());
1698 RTC_RETURN_IF_ERROR(status);
1699
1700 // Get decoders.
1701 config.codecs.clear();
1702 for (int i = 0; i < receiver_config.decoders_size(); i++) {
1703 RTC_PARSE_CHECK_OR_RETURN(receiver_config.decoders(i).has_name());
1704 RTC_PARSE_CHECK_OR_RETURN(receiver_config.decoders(i).has_payload_type());
1705 int rtx_payload_type = 0;
1706 auto rtx_it = rtx_map.find(receiver_config.decoders(i).payload_type());
1707 if (rtx_it != rtx_map.end()) {
1708 rtx_payload_type = rtx_it->second.rtx_payload_type();
1709 if (config.rtx_ssrc != 0 &&
1710 config.rtx_ssrc != rtx_it->second.rtx_ssrc()) {
1711 RTC_LOG(LS_WARNING)
1712 << "RtcEventLog protobuf contained different SSRCs for "
1713 "different received RTX payload types. Will only use "
1714 "rtx_ssrc = "
1715 << config.rtx_ssrc << ".";
1716 } else {
1717 config.rtx_ssrc = rtx_it->second.rtx_ssrc();
1718 }
1719 }
1720 config.codecs.emplace_back(receiver_config.decoders(i).name(),
1721 receiver_config.decoders(i).payload_type(),
1722 rtx_payload_type);
1723 }
1724 return config;
1725 }
1726
1727 ParsedRtcEventLog::ParseStatusOr<rtclog::StreamConfig>
GetVideoSendConfig(const rtclog::Event & event) const1728 ParsedRtcEventLog::GetVideoSendConfig(const rtclog::Event& event) const {
1729 rtclog::StreamConfig config;
1730 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1731 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1732 rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
1733 RTC_PARSE_CHECK_OR_RETURN(event.has_video_sender_config());
1734 const rtclog::VideoSendConfig& sender_config = event.video_sender_config();
1735
1736 // Get SSRCs.
1737 // VideoSendStreamConfig no longer stores multiple SSRCs. If you are
1738 // analyzing a very old log, try building the parser from the same
1739 // WebRTC version.
1740 RTC_PARSE_CHECK_OR_RETURN_EQ(sender_config.ssrcs_size(), 1);
1741 config.local_ssrc = sender_config.ssrcs(0);
1742 RTC_PARSE_CHECK_OR_RETURN_LE(sender_config.rtx_ssrcs_size(), 1);
1743 if (sender_config.rtx_ssrcs_size() == 1) {
1744 config.rtx_ssrc = sender_config.rtx_ssrcs(0);
1745 }
1746
1747 // Get header extensions.
1748 auto status = GetHeaderExtensions(&config.rtp_extensions,
1749 sender_config.header_extensions());
1750 RTC_RETURN_IF_ERROR(status);
1751
1752 // Get the codec.
1753 RTC_PARSE_CHECK_OR_RETURN(sender_config.has_encoder());
1754 RTC_PARSE_CHECK_OR_RETURN(sender_config.encoder().has_name());
1755 RTC_PARSE_CHECK_OR_RETURN(sender_config.encoder().has_payload_type());
1756 config.codecs.emplace_back(
1757 sender_config.encoder().name(), sender_config.encoder().payload_type(),
1758 sender_config.has_rtx_payload_type() ? sender_config.rtx_payload_type()
1759 : 0);
1760 return config;
1761 }
1762
1763 ParsedRtcEventLog::ParseStatusOr<rtclog::StreamConfig>
GetAudioReceiveConfig(const rtclog::Event & event) const1764 ParsedRtcEventLog::GetAudioReceiveConfig(const rtclog::Event& event) const {
1765 rtclog::StreamConfig config;
1766 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1767 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1768 rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT);
1769 RTC_PARSE_CHECK_OR_RETURN(event.has_audio_receiver_config());
1770 const rtclog::AudioReceiveConfig& receiver_config =
1771 event.audio_receiver_config();
1772 // Get SSRCs.
1773 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_remote_ssrc());
1774 config.remote_ssrc = receiver_config.remote_ssrc();
1775 RTC_PARSE_CHECK_OR_RETURN(receiver_config.has_local_ssrc());
1776 config.local_ssrc = receiver_config.local_ssrc();
1777 // Get header extensions.
1778 auto status = GetHeaderExtensions(&config.rtp_extensions,
1779 receiver_config.header_extensions());
1780 RTC_RETURN_IF_ERROR(status);
1781
1782 return config;
1783 }
1784
1785 ParsedRtcEventLog::ParseStatusOr<rtclog::StreamConfig>
GetAudioSendConfig(const rtclog::Event & event) const1786 ParsedRtcEventLog::GetAudioSendConfig(const rtclog::Event& event) const {
1787 rtclog::StreamConfig config;
1788 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1789 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1790 rtclog::Event::AUDIO_SENDER_CONFIG_EVENT);
1791 RTC_PARSE_CHECK_OR_RETURN(event.has_audio_sender_config());
1792 const rtclog::AudioSendConfig& sender_config = event.audio_sender_config();
1793 // Get SSRCs.
1794 RTC_PARSE_CHECK_OR_RETURN(sender_config.has_ssrc());
1795 config.local_ssrc = sender_config.ssrc();
1796 // Get header extensions.
1797 auto status = GetHeaderExtensions(&config.rtp_extensions,
1798 sender_config.header_extensions());
1799 RTC_RETURN_IF_ERROR(status);
1800
1801 return config;
1802 }
1803
1804 ParsedRtcEventLog::ParseStatusOr<LoggedAudioPlayoutEvent>
GetAudioPlayout(const rtclog::Event & event) const1805 ParsedRtcEventLog::GetAudioPlayout(const rtclog::Event& event) const {
1806 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1807 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1808 rtclog::Event::AUDIO_PLAYOUT_EVENT);
1809 RTC_PARSE_CHECK_OR_RETURN(event.has_audio_playout_event());
1810 const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
1811 LoggedAudioPlayoutEvent res;
1812 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1813 res.timestamp_us = event.timestamp_us();
1814 RTC_PARSE_CHECK_OR_RETURN(playout_event.has_local_ssrc());
1815 res.ssrc = playout_event.local_ssrc();
1816 return res;
1817 }
1818
1819 ParsedRtcEventLog::ParseStatusOr<LoggedBweLossBasedUpdate>
GetLossBasedBweUpdate(const rtclog::Event & event) const1820 ParsedRtcEventLog::GetLossBasedBweUpdate(const rtclog::Event& event) const {
1821 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1822 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1823 rtclog::Event::LOSS_BASED_BWE_UPDATE);
1824 RTC_PARSE_CHECK_OR_RETURN(event.has_loss_based_bwe_update());
1825 const rtclog::LossBasedBweUpdate& loss_event = event.loss_based_bwe_update();
1826
1827 LoggedBweLossBasedUpdate bwe_update;
1828 RTC_CHECK(event.has_timestamp_us());
1829 bwe_update.timestamp_us = event.timestamp_us();
1830 RTC_PARSE_CHECK_OR_RETURN(loss_event.has_bitrate_bps());
1831 bwe_update.bitrate_bps = loss_event.bitrate_bps();
1832 RTC_PARSE_CHECK_OR_RETURN(loss_event.has_fraction_loss());
1833 bwe_update.fraction_lost = loss_event.fraction_loss();
1834 RTC_PARSE_CHECK_OR_RETURN(loss_event.has_total_packets());
1835 bwe_update.expected_packets = loss_event.total_packets();
1836 return bwe_update;
1837 }
1838
1839 ParsedRtcEventLog::ParseStatusOr<LoggedBweDelayBasedUpdate>
GetDelayBasedBweUpdate(const rtclog::Event & event) const1840 ParsedRtcEventLog::GetDelayBasedBweUpdate(const rtclog::Event& event) const {
1841 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1842 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1843 rtclog::Event::DELAY_BASED_BWE_UPDATE);
1844 RTC_PARSE_CHECK_OR_RETURN(event.has_delay_based_bwe_update());
1845 const rtclog::DelayBasedBweUpdate& delay_event =
1846 event.delay_based_bwe_update();
1847
1848 LoggedBweDelayBasedUpdate res;
1849 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1850 res.timestamp_us = event.timestamp_us();
1851 RTC_PARSE_CHECK_OR_RETURN(delay_event.has_bitrate_bps());
1852 res.bitrate_bps = delay_event.bitrate_bps();
1853 RTC_PARSE_CHECK_OR_RETURN(delay_event.has_detector_state());
1854 res.detector_state = GetRuntimeDetectorState(delay_event.detector_state());
1855 return res;
1856 }
1857
1858 ParsedRtcEventLog::ParseStatusOr<LoggedAudioNetworkAdaptationEvent>
GetAudioNetworkAdaptation(const rtclog::Event & event) const1859 ParsedRtcEventLog::GetAudioNetworkAdaptation(const rtclog::Event& event) const {
1860 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1861 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1862 rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT);
1863 RTC_PARSE_CHECK_OR_RETURN(event.has_audio_network_adaptation());
1864 const rtclog::AudioNetworkAdaptation& ana_event =
1865 event.audio_network_adaptation();
1866
1867 LoggedAudioNetworkAdaptationEvent res;
1868 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1869 res.timestamp_us = event.timestamp_us();
1870 if (ana_event.has_bitrate_bps())
1871 res.config.bitrate_bps = ana_event.bitrate_bps();
1872 if (ana_event.has_enable_fec())
1873 res.config.enable_fec = ana_event.enable_fec();
1874 if (ana_event.has_enable_dtx())
1875 res.config.enable_dtx = ana_event.enable_dtx();
1876 if (ana_event.has_frame_length_ms())
1877 res.config.frame_length_ms = ana_event.frame_length_ms();
1878 if (ana_event.has_num_channels())
1879 res.config.num_channels = ana_event.num_channels();
1880 if (ana_event.has_uplink_packet_loss_fraction())
1881 res.config.uplink_packet_loss_fraction =
1882 ana_event.uplink_packet_loss_fraction();
1883 return res;
1884 }
1885
1886 ParsedRtcEventLog::ParseStatusOr<LoggedBweProbeClusterCreatedEvent>
GetBweProbeClusterCreated(const rtclog::Event & event) const1887 ParsedRtcEventLog::GetBweProbeClusterCreated(const rtclog::Event& event) const {
1888 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1889 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1890 rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT);
1891 RTC_PARSE_CHECK_OR_RETURN(event.has_probe_cluster());
1892 const rtclog::BweProbeCluster& pcc_event = event.probe_cluster();
1893 LoggedBweProbeClusterCreatedEvent res;
1894 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1895 res.timestamp_us = event.timestamp_us();
1896 RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_id());
1897 res.id = pcc_event.id();
1898 RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_bitrate_bps());
1899 res.bitrate_bps = pcc_event.bitrate_bps();
1900 RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_min_packets());
1901 res.min_packets = pcc_event.min_packets();
1902 RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_min_bytes());
1903 res.min_bytes = pcc_event.min_bytes();
1904 return res;
1905 }
1906
1907 ParsedRtcEventLog::ParseStatusOr<LoggedBweProbeFailureEvent>
GetBweProbeFailure(const rtclog::Event & event) const1908 ParsedRtcEventLog::GetBweProbeFailure(const rtclog::Event& event) const {
1909 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1910 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1911 rtclog::Event::BWE_PROBE_RESULT_EVENT);
1912 RTC_PARSE_CHECK_OR_RETURN(event.has_probe_result());
1913 const rtclog::BweProbeResult& pr_event = event.probe_result();
1914 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_result());
1915 RTC_PARSE_CHECK_OR_RETURN_NE(pr_event.result(),
1916 rtclog::BweProbeResult::SUCCESS);
1917
1918 LoggedBweProbeFailureEvent res;
1919 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1920 res.timestamp_us = event.timestamp_us();
1921 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_id());
1922 res.id = pr_event.id();
1923 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_result());
1924 if (pr_event.result() ==
1925 rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL) {
1926 res.failure_reason = ProbeFailureReason::kInvalidSendReceiveInterval;
1927 } else if (pr_event.result() ==
1928 rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO) {
1929 res.failure_reason = ProbeFailureReason::kInvalidSendReceiveRatio;
1930 } else if (pr_event.result() == rtclog::BweProbeResult::TIMEOUT) {
1931 res.failure_reason = ProbeFailureReason::kTimeout;
1932 } else {
1933 RTC_NOTREACHED();
1934 }
1935 RTC_PARSE_CHECK_OR_RETURN(!pr_event.has_bitrate_bps());
1936
1937 return res;
1938 }
1939
1940 ParsedRtcEventLog::ParseStatusOr<LoggedBweProbeSuccessEvent>
GetBweProbeSuccess(const rtclog::Event & event) const1941 ParsedRtcEventLog::GetBweProbeSuccess(const rtclog::Event& event) const {
1942 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1943 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(),
1944 rtclog::Event::BWE_PROBE_RESULT_EVENT);
1945 RTC_PARSE_CHECK_OR_RETURN(event.has_probe_result());
1946 const rtclog::BweProbeResult& pr_event = event.probe_result();
1947 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_result());
1948 RTC_PARSE_CHECK_OR_RETURN_EQ(pr_event.result(),
1949 rtclog::BweProbeResult::SUCCESS);
1950
1951 LoggedBweProbeSuccessEvent res;
1952 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1953 res.timestamp_us = event.timestamp_us();
1954 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_id());
1955 res.id = pr_event.id();
1956 RTC_PARSE_CHECK_OR_RETURN(pr_event.has_bitrate_bps());
1957 res.bitrate_bps = pr_event.bitrate_bps();
1958
1959 return res;
1960 }
1961
1962 ParsedRtcEventLog::ParseStatusOr<LoggedAlrStateEvent>
GetAlrState(const rtclog::Event & event) const1963 ParsedRtcEventLog::GetAlrState(const rtclog::Event& event) const {
1964 RTC_PARSE_CHECK_OR_RETURN(event.has_type());
1965 RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::ALR_STATE_EVENT);
1966 RTC_PARSE_CHECK_OR_RETURN(event.has_alr_state());
1967 const rtclog::AlrState& alr_event = event.alr_state();
1968 LoggedAlrStateEvent res;
1969 RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
1970 res.timestamp_us = event.timestamp_us();
1971 RTC_PARSE_CHECK_OR_RETURN(alr_event.has_in_alr());
1972 res.in_alr = alr_event.in_alr();
1973
1974 return res;
1975 }
1976
1977 ParsedRtcEventLog::ParseStatusOr<LoggedIceCandidatePairConfig>
GetIceCandidatePairConfig(const rtclog::Event & rtc_event) const1978 ParsedRtcEventLog::GetIceCandidatePairConfig(
1979 const rtclog::Event& rtc_event) const {
1980 RTC_PARSE_CHECK_OR_RETURN(rtc_event.has_type());
1981 RTC_PARSE_CHECK_OR_RETURN_EQ(rtc_event.type(),
1982 rtclog::Event::ICE_CANDIDATE_PAIR_CONFIG);
1983 LoggedIceCandidatePairConfig res;
1984 const rtclog::IceCandidatePairConfig& config =
1985 rtc_event.ice_candidate_pair_config();
1986 RTC_CHECK(rtc_event.has_timestamp_us());
1987 res.timestamp_us = rtc_event.timestamp_us();
1988 RTC_PARSE_CHECK_OR_RETURN(config.has_config_type());
1989 res.type = GetRuntimeIceCandidatePairConfigType(config.config_type());
1990 RTC_PARSE_CHECK_OR_RETURN(config.has_candidate_pair_id());
1991 res.candidate_pair_id = config.candidate_pair_id();
1992 RTC_PARSE_CHECK_OR_RETURN(config.has_local_candidate_type());
1993 res.local_candidate_type =
1994 GetRuntimeIceCandidateType(config.local_candidate_type());
1995 RTC_PARSE_CHECK_OR_RETURN(config.has_local_relay_protocol());
1996 res.local_relay_protocol =
1997 GetRuntimeIceCandidatePairProtocol(config.local_relay_protocol());
1998 RTC_PARSE_CHECK_OR_RETURN(config.has_local_network_type());
1999 res.local_network_type =
2000 GetRuntimeIceCandidateNetworkType(config.local_network_type());
2001 RTC_PARSE_CHECK_OR_RETURN(config.has_local_address_family());
2002 res.local_address_family =
2003 GetRuntimeIceCandidatePairAddressFamily(config.local_address_family());
2004 RTC_PARSE_CHECK_OR_RETURN(config.has_remote_candidate_type());
2005 res.remote_candidate_type =
2006 GetRuntimeIceCandidateType(config.remote_candidate_type());
2007 RTC_PARSE_CHECK_OR_RETURN(config.has_remote_address_family());
2008 res.remote_address_family =
2009 GetRuntimeIceCandidatePairAddressFamily(config.remote_address_family());
2010 RTC_PARSE_CHECK_OR_RETURN(config.has_candidate_pair_protocol());
2011 res.candidate_pair_protocol =
2012 GetRuntimeIceCandidatePairProtocol(config.candidate_pair_protocol());
2013 return res;
2014 }
2015
2016 ParsedRtcEventLog::ParseStatusOr<LoggedIceCandidatePairEvent>
GetIceCandidatePairEvent(const rtclog::Event & rtc_event) const2017 ParsedRtcEventLog::GetIceCandidatePairEvent(
2018 const rtclog::Event& rtc_event) const {
2019 RTC_PARSE_CHECK_OR_RETURN(rtc_event.has_type());
2020 RTC_PARSE_CHECK_OR_RETURN_EQ(rtc_event.type(),
2021 rtclog::Event::ICE_CANDIDATE_PAIR_EVENT);
2022 LoggedIceCandidatePairEvent res;
2023 const rtclog::IceCandidatePairEvent& event =
2024 rtc_event.ice_candidate_pair_event();
2025 RTC_CHECK(rtc_event.has_timestamp_us());
2026 res.timestamp_us = rtc_event.timestamp_us();
2027 RTC_PARSE_CHECK_OR_RETURN(event.has_event_type());
2028 res.type = GetRuntimeIceCandidatePairEventType(event.event_type());
2029 RTC_PARSE_CHECK_OR_RETURN(event.has_candidate_pair_id());
2030 res.candidate_pair_id = event.candidate_pair_id();
2031 // transaction_id is not supported by rtclog::Event
2032 res.transaction_id = 0;
2033 return res;
2034 }
2035
2036 // Returns the MediaType for registered SSRCs. Search from the end to use last
2037 // registered types first.
GetMediaType(uint32_t ssrc,PacketDirection direction) const2038 ParsedRtcEventLog::MediaType ParsedRtcEventLog::GetMediaType(
2039 uint32_t ssrc,
2040 PacketDirection direction) const {
2041 if (direction == kIncomingPacket) {
2042 if (std::find(incoming_video_ssrcs_.begin(), incoming_video_ssrcs_.end(),
2043 ssrc) != incoming_video_ssrcs_.end()) {
2044 return MediaType::VIDEO;
2045 }
2046 if (std::find(incoming_audio_ssrcs_.begin(), incoming_audio_ssrcs_.end(),
2047 ssrc) != incoming_audio_ssrcs_.end()) {
2048 return MediaType::AUDIO;
2049 }
2050 } else {
2051 if (std::find(outgoing_video_ssrcs_.begin(), outgoing_video_ssrcs_.end(),
2052 ssrc) != outgoing_video_ssrcs_.end()) {
2053 return MediaType::VIDEO;
2054 }
2055 if (std::find(outgoing_audio_ssrcs_.begin(), outgoing_audio_ssrcs_.end(),
2056 ssrc) != outgoing_audio_ssrcs_.end()) {
2057 return MediaType::AUDIO;
2058 }
2059 }
2060 return MediaType::ANY;
2061 }
2062
GetRouteChanges() const2063 std::vector<InferredRouteChangeEvent> ParsedRtcEventLog::GetRouteChanges()
2064 const {
2065 std::vector<InferredRouteChangeEvent> route_changes;
2066 for (auto& candidate : ice_candidate_pair_configs()) {
2067 if (candidate.type == IceCandidatePairConfigType::kSelected) {
2068 InferredRouteChangeEvent route;
2069 route.route_id = candidate.candidate_pair_id;
2070 route.log_time = Timestamp::Millis(candidate.log_time_ms());
2071
2072 route.send_overhead = kUdpOverhead + kSrtpOverhead + kIpv4Overhead;
2073 if (candidate.remote_address_family ==
2074 IceCandidatePairAddressFamily::kIpv6)
2075 route.send_overhead += kIpv6Overhead - kIpv4Overhead;
2076 if (candidate.remote_candidate_type != IceCandidateType::kLocal)
2077 route.send_overhead += kStunOverhead;
2078 route.return_overhead = kUdpOverhead + kSrtpOverhead + kIpv4Overhead;
2079 if (candidate.remote_address_family ==
2080 IceCandidatePairAddressFamily::kIpv6)
2081 route.return_overhead += kIpv6Overhead - kIpv4Overhead;
2082 if (candidate.remote_candidate_type != IceCandidateType::kLocal)
2083 route.return_overhead += kStunOverhead;
2084 route_changes.push_back(route);
2085 }
2086 }
2087 return route_changes;
2088 }
2089
GetPacketInfos(PacketDirection direction) const2090 std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
2091 PacketDirection direction) const {
2092 std::map<uint32_t, MediaStreamInfo> streams;
2093 if (direction == PacketDirection::kIncomingPacket) {
2094 AddRecvStreamInfos(&streams, audio_recv_configs(), LoggedMediaType::kAudio);
2095 AddRecvStreamInfos(&streams, video_recv_configs(), LoggedMediaType::kVideo);
2096 } else if (direction == PacketDirection::kOutgoingPacket) {
2097 AddSendStreamInfos(&streams, audio_send_configs(), LoggedMediaType::kAudio);
2098 AddSendStreamInfos(&streams, video_send_configs(), LoggedMediaType::kVideo);
2099 }
2100
2101 std::vector<OverheadChangeEvent> overheads =
2102 GetOverheadChangingEvents(GetRouteChanges(), direction);
2103 auto overhead_iter = overheads.begin();
2104 std::vector<LoggedPacketInfo> packets;
2105 std::map<int64_t, size_t> indices;
2106 uint16_t current_overhead = kDefaultOverhead;
2107 Timestamp last_log_time = Timestamp::Zero();
2108 SequenceNumberUnwrapper seq_num_unwrapper;
2109
2110 auto advance_time = [&](Timestamp new_log_time) {
2111 if (overhead_iter != overheads.end() &&
2112 new_log_time >= overhead_iter->timestamp) {
2113 current_overhead = overhead_iter->overhead;
2114 ++overhead_iter;
2115 }
2116 // If we have a large time delta, it can be caused by a gap in logging,
2117 // therefore we don't want to match up sequence numbers as we might have had
2118 // a wraparound.
2119 if (new_log_time - last_log_time > TimeDelta::Seconds(30)) {
2120 seq_num_unwrapper = SequenceNumberUnwrapper();
2121 indices.clear();
2122 }
2123 RTC_DCHECK(new_log_time >= last_log_time);
2124 last_log_time = new_log_time;
2125 };
2126
2127 auto rtp_handler = [&](const LoggedRtpPacket& rtp) {
2128 advance_time(Timestamp::Millis(rtp.log_time_ms()));
2129 MediaStreamInfo* stream = &streams[rtp.header.ssrc];
2130 Timestamp capture_time = Timestamp::MinusInfinity();
2131 if (!stream->rtx) {
2132 // RTX copy the timestamp of the retransmitted packets. This means that
2133 // RTX streams don't have a unique clock offset and frequency, so
2134 // the RTP timstamps can't be unwrapped.
2135
2136 // Add an offset to avoid |capture_ticks| to become negative in the case
2137 // of reordering.
2138 constexpr int64_t kStartingCaptureTimeTicks = 90 * 48 * 1000;
2139 int64_t capture_ticks =
2140 kStartingCaptureTimeTicks +
2141 stream->unwrap_capture_ticks.Unwrap(rtp.header.timestamp);
2142 // TODO(srte): Use logged sample rate when it is added to the format.
2143 capture_time = Timestamp::Seconds(
2144 capture_ticks /
2145 (stream->media_type == LoggedMediaType::kAudio ? 48000.0 : 90000.0));
2146 }
2147 LoggedPacketInfo logged(rtp, stream->media_type, stream->rtx, capture_time);
2148 logged.overhead = current_overhead;
2149 if (logged.has_transport_seq_no) {
2150 logged.log_feedback_time = Timestamp::PlusInfinity();
2151 int64_t unwrapped_seq_num =
2152 seq_num_unwrapper.Unwrap(logged.transport_seq_no);
2153 if (indices.find(unwrapped_seq_num) != indices.end()) {
2154 auto prev = packets[indices[unwrapped_seq_num]];
2155 RTC_LOG(LS_WARNING)
2156 << "Repeated sent packet sequence number: " << unwrapped_seq_num
2157 << " Packet time:" << prev.log_packet_time.seconds() << "s vs "
2158 << logged.log_packet_time.seconds()
2159 << "s at:" << rtp.log_time_ms() / 1000;
2160 }
2161 indices[unwrapped_seq_num] = packets.size();
2162 }
2163 packets.push_back(logged);
2164 };
2165
2166 Timestamp feedback_base_time = Timestamp::MinusInfinity();
2167 absl::optional<int64_t> last_feedback_base_time_us;
2168
2169 auto feedback_handler =
2170 [&](const LoggedRtcpPacketTransportFeedback& logged_rtcp) {
2171 auto log_feedback_time = Timestamp::Millis(logged_rtcp.log_time_ms());
2172 advance_time(log_feedback_time);
2173 const auto& feedback = logged_rtcp.transport_feedback;
2174 // Add timestamp deltas to a local time base selected on first packet
2175 // arrival. This won't be the true time base, but makes it easier to
2176 // manually inspect time stamps.
2177 if (!last_feedback_base_time_us) {
2178 feedback_base_time = log_feedback_time;
2179 } else {
2180 feedback_base_time += TimeDelta::Micros(
2181 feedback.GetBaseDeltaUs(*last_feedback_base_time_us));
2182 }
2183 last_feedback_base_time_us = feedback.GetBaseTimeUs();
2184
2185 std::vector<LoggedPacketInfo*> packet_feedbacks;
2186 packet_feedbacks.reserve(feedback.GetAllPackets().size());
2187 Timestamp receive_timestamp = feedback_base_time;
2188 std::vector<int64_t> unknown_seq_nums;
2189 for (const auto& packet : feedback.GetAllPackets()) {
2190 int64_t unwrapped_seq_num =
2191 seq_num_unwrapper.Unwrap(packet.sequence_number());
2192 auto it = indices.find(unwrapped_seq_num);
2193 if (it == indices.end()) {
2194 unknown_seq_nums.push_back(unwrapped_seq_num);
2195 continue;
2196 }
2197 LoggedPacketInfo* sent = &packets[it->second];
2198 if (log_feedback_time - sent->log_packet_time >
2199 TimeDelta::Seconds(60)) {
2200 RTC_LOG(LS_WARNING)
2201 << "Received very late feedback, possibly due to wraparound.";
2202 continue;
2203 }
2204 if (packet.received()) {
2205 receive_timestamp += TimeDelta::Micros(packet.delta_us());
2206 if (sent->reported_recv_time.IsInfinite()) {
2207 sent->reported_recv_time =
2208 Timestamp::Millis(receive_timestamp.ms());
2209 sent->log_feedback_time = log_feedback_time;
2210 }
2211 } else {
2212 if (sent->reported_recv_time.IsInfinite() &&
2213 sent->log_feedback_time.IsInfinite()) {
2214 sent->reported_recv_time = Timestamp::PlusInfinity();
2215 sent->log_feedback_time = log_feedback_time;
2216 }
2217 }
2218 packet_feedbacks.push_back(sent);
2219 }
2220 if (!unknown_seq_nums.empty()) {
2221 RTC_LOG(LS_WARNING)
2222 << "Received feedback for unknown packets: "
2223 << unknown_seq_nums.front() << " - " << unknown_seq_nums.back();
2224 }
2225 if (packet_feedbacks.empty())
2226 return;
2227 LoggedPacketInfo* last = packet_feedbacks.back();
2228 last->last_in_feedback = true;
2229 for (LoggedPacketInfo* fb : packet_feedbacks) {
2230 if (direction == PacketDirection::kOutgoingPacket) {
2231 fb->feedback_hold_duration =
2232 last->reported_recv_time - fb->reported_recv_time;
2233 } else {
2234 fb->feedback_hold_duration =
2235 log_feedback_time - fb->log_packet_time;
2236 }
2237 }
2238 };
2239
2240 RtcEventProcessor process;
2241 for (const auto& rtp_packets : rtp_packets_by_ssrc(direction)) {
2242 process.AddEvents(rtp_packets.packet_view, rtp_handler);
2243 }
2244 if (direction == PacketDirection::kOutgoingPacket) {
2245 process.AddEvents(incoming_transport_feedback_, feedback_handler);
2246 } else {
2247 process.AddEvents(outgoing_transport_feedback_, feedback_handler);
2248 }
2249 process.ProcessEventsInOrder();
2250 return packets;
2251 }
2252
GetIceCandidates() const2253 std::vector<LoggedIceCandidatePairConfig> ParsedRtcEventLog::GetIceCandidates()
2254 const {
2255 std::vector<LoggedIceCandidatePairConfig> candidates;
2256 std::set<uint32_t> added;
2257 for (auto& candidate : ice_candidate_pair_configs()) {
2258 if (added.find(candidate.candidate_pair_id) == added.end()) {
2259 candidates.push_back(candidate);
2260 added.insert(candidate.candidate_pair_id);
2261 }
2262 }
2263 return candidates;
2264 }
2265
GetIceEvents() const2266 std::vector<LoggedIceEvent> ParsedRtcEventLog::GetIceEvents() const {
2267 using CheckType = IceCandidatePairEventType;
2268 using ConfigType = IceCandidatePairConfigType;
2269 using Combined = LoggedIceEventType;
2270 std::map<CheckType, Combined> check_map(
2271 {{CheckType::kCheckSent, Combined::kCheckSent},
2272 {CheckType::kCheckReceived, Combined::kCheckReceived},
2273 {CheckType::kCheckResponseSent, Combined::kCheckResponseSent},
2274 {CheckType::kCheckResponseReceived, Combined::kCheckResponseReceived}});
2275 std::map<ConfigType, Combined> config_map(
2276 {{ConfigType::kAdded, Combined::kAdded},
2277 {ConfigType::kUpdated, Combined::kUpdated},
2278 {ConfigType::kDestroyed, Combined::kDestroyed},
2279 {ConfigType::kSelected, Combined::kSelected}});
2280 std::vector<LoggedIceEvent> log_events;
2281 auto handle_check = [&](const LoggedIceCandidatePairEvent& check) {
2282 log_events.push_back(LoggedIceEvent{check.candidate_pair_id,
2283 Timestamp::Millis(check.log_time_ms()),
2284 check_map[check.type]});
2285 };
2286 auto handle_config = [&](const LoggedIceCandidatePairConfig& conf) {
2287 log_events.push_back(LoggedIceEvent{conf.candidate_pair_id,
2288 Timestamp::Millis(conf.log_time_ms()),
2289 config_map[conf.type]});
2290 };
2291 RtcEventProcessor process;
2292 process.AddEvents(ice_candidate_pair_events(), handle_check);
2293 process.AddEvents(ice_candidate_pair_configs(), handle_config);
2294 process.ProcessEventsInOrder();
2295 return log_events;
2296 }
2297
GetNetworkTrace(const ParsedRtcEventLog & parsed_log)2298 const std::vector<MatchedSendArrivalTimes> GetNetworkTrace(
2299 const ParsedRtcEventLog& parsed_log) {
2300 std::vector<MatchedSendArrivalTimes> rtp_rtcp_matched;
2301 for (auto& packet :
2302 parsed_log.GetPacketInfos(PacketDirection::kOutgoingPacket)) {
2303 if (packet.log_feedback_time.IsFinite()) {
2304 rtp_rtcp_matched.emplace_back(packet.log_feedback_time.ms(),
2305 packet.log_packet_time.ms(),
2306 packet.reported_recv_time.ms_or(
2307 MatchedSendArrivalTimes::kNotReceived),
2308 packet.size);
2309 }
2310 }
2311 return rtp_rtcp_matched;
2312 }
2313
2314 // Helper functions for new format start here
StoreParsedNewFormatEvent(const rtclog2::EventStream & stream)2315 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedNewFormatEvent(
2316 const rtclog2::EventStream& stream) {
2317 RTC_DCHECK_EQ(stream.stream_size(), 0); // No legacy format event.
2318
2319 RTC_DCHECK_EQ(
2320 stream.incoming_rtp_packets_size() + stream.outgoing_rtp_packets_size() +
2321 stream.incoming_rtcp_packets_size() +
2322 stream.outgoing_rtcp_packets_size() +
2323 stream.audio_playout_events_size() + stream.begin_log_events_size() +
2324 stream.end_log_events_size() + stream.loss_based_bwe_updates_size() +
2325 stream.delay_based_bwe_updates_size() +
2326 stream.dtls_transport_state_events_size() +
2327 stream.dtls_writable_states_size() +
2328 stream.audio_network_adaptations_size() +
2329 stream.probe_clusters_size() + stream.probe_success_size() +
2330 stream.probe_failure_size() + stream.alr_states_size() +
2331 stream.route_changes_size() + stream.remote_estimates_size() +
2332 stream.ice_candidate_configs_size() +
2333 stream.ice_candidate_events_size() +
2334 stream.audio_recv_stream_configs_size() +
2335 stream.audio_send_stream_configs_size() +
2336 stream.video_recv_stream_configs_size() +
2337 stream.video_send_stream_configs_size() +
2338 stream.generic_packets_sent_size() +
2339 stream.generic_packets_received_size() +
2340 stream.generic_acks_received_size(),
2341 1u);
2342
2343 if (stream.incoming_rtp_packets_size() == 1) {
2344 return StoreIncomingRtpPackets(stream.incoming_rtp_packets(0));
2345 } else if (stream.outgoing_rtp_packets_size() == 1) {
2346 return StoreOutgoingRtpPackets(stream.outgoing_rtp_packets(0));
2347 } else if (stream.incoming_rtcp_packets_size() == 1) {
2348 return StoreIncomingRtcpPackets(stream.incoming_rtcp_packets(0));
2349 } else if (stream.outgoing_rtcp_packets_size() == 1) {
2350 return StoreOutgoingRtcpPackets(stream.outgoing_rtcp_packets(0));
2351 } else if (stream.audio_playout_events_size() == 1) {
2352 return StoreAudioPlayoutEvent(stream.audio_playout_events(0));
2353 } else if (stream.begin_log_events_size() == 1) {
2354 return StoreStartEvent(stream.begin_log_events(0));
2355 } else if (stream.end_log_events_size() == 1) {
2356 return StoreStopEvent(stream.end_log_events(0));
2357 } else if (stream.loss_based_bwe_updates_size() == 1) {
2358 return StoreBweLossBasedUpdate(stream.loss_based_bwe_updates(0));
2359 } else if (stream.delay_based_bwe_updates_size() == 1) {
2360 return StoreBweDelayBasedUpdate(stream.delay_based_bwe_updates(0));
2361 } else if (stream.dtls_transport_state_events_size() == 1) {
2362 return StoreDtlsTransportState(stream.dtls_transport_state_events(0));
2363 } else if (stream.dtls_writable_states_size() == 1) {
2364 return StoreDtlsWritableState(stream.dtls_writable_states(0));
2365 } else if (stream.audio_network_adaptations_size() == 1) {
2366 return StoreAudioNetworkAdaptationEvent(
2367 stream.audio_network_adaptations(0));
2368 } else if (stream.probe_clusters_size() == 1) {
2369 return StoreBweProbeClusterCreated(stream.probe_clusters(0));
2370 } else if (stream.probe_success_size() == 1) {
2371 return StoreBweProbeSuccessEvent(stream.probe_success(0));
2372 } else if (stream.probe_failure_size() == 1) {
2373 return StoreBweProbeFailureEvent(stream.probe_failure(0));
2374 } else if (stream.alr_states_size() == 1) {
2375 return StoreAlrStateEvent(stream.alr_states(0));
2376 } else if (stream.route_changes_size() == 1) {
2377 return StoreRouteChangeEvent(stream.route_changes(0));
2378 } else if (stream.remote_estimates_size() == 1) {
2379 return StoreRemoteEstimateEvent(stream.remote_estimates(0));
2380 } else if (stream.ice_candidate_configs_size() == 1) {
2381 return StoreIceCandidatePairConfig(stream.ice_candidate_configs(0));
2382 } else if (stream.ice_candidate_events_size() == 1) {
2383 return StoreIceCandidateEvent(stream.ice_candidate_events(0));
2384 } else if (stream.audio_recv_stream_configs_size() == 1) {
2385 return StoreAudioRecvConfig(stream.audio_recv_stream_configs(0));
2386 } else if (stream.audio_send_stream_configs_size() == 1) {
2387 return StoreAudioSendConfig(stream.audio_send_stream_configs(0));
2388 } else if (stream.video_recv_stream_configs_size() == 1) {
2389 return StoreVideoRecvConfig(stream.video_recv_stream_configs(0));
2390 } else if (stream.video_send_stream_configs_size() == 1) {
2391 return StoreVideoSendConfig(stream.video_send_stream_configs(0));
2392 } else if (stream.generic_packets_received_size() == 1) {
2393 return StoreGenericPacketReceivedEvent(stream.generic_packets_received(0));
2394 } else if (stream.generic_packets_sent_size() == 1) {
2395 return StoreGenericPacketSentEvent(stream.generic_packets_sent(0));
2396 } else if (stream.generic_acks_received_size() == 1) {
2397 return StoreGenericAckReceivedEvent(stream.generic_acks_received(0));
2398 } else {
2399 RTC_NOTREACHED();
2400 return ParseStatus::Success();
2401 }
2402 }
2403
StoreAlrStateEvent(const rtclog2::AlrState & proto)2404 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAlrStateEvent(
2405 const rtclog2::AlrState& proto) {
2406 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2407 RTC_PARSE_CHECK_OR_RETURN(proto.has_in_alr());
2408 LoggedAlrStateEvent alr_event;
2409 alr_event.timestamp_us = proto.timestamp_ms() * 1000;
2410 alr_event.in_alr = proto.in_alr();
2411
2412 alr_state_events_.push_back(alr_event);
2413 // TODO(terelius): Should we delta encode this event type?
2414 return ParseStatus::Success();
2415 }
2416
StoreRouteChangeEvent(const rtclog2::RouteChange & proto)2417 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreRouteChangeEvent(
2418 const rtclog2::RouteChange& proto) {
2419 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2420 RTC_PARSE_CHECK_OR_RETURN(proto.has_connected());
2421 RTC_PARSE_CHECK_OR_RETURN(proto.has_overhead());
2422 LoggedRouteChangeEvent route_event;
2423 route_event.timestamp_ms = proto.timestamp_ms();
2424 route_event.connected = proto.connected();
2425 route_event.overhead = proto.overhead();
2426
2427 route_change_events_.push_back(route_event);
2428 // TODO(terelius): Should we delta encode this event type?
2429 return ParseStatus::Success();
2430 }
2431
StoreRemoteEstimateEvent(const rtclog2::RemoteEstimates & proto)2432 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreRemoteEstimateEvent(
2433 const rtclog2::RemoteEstimates& proto) {
2434 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2435 // Base event
2436 LoggedRemoteEstimateEvent base_event;
2437 base_event.timestamp_ms = proto.timestamp_ms();
2438
2439 absl::optional<uint64_t> base_link_capacity_lower_kbps;
2440 if (proto.has_link_capacity_lower_kbps()) {
2441 base_link_capacity_lower_kbps = proto.link_capacity_lower_kbps();
2442 base_event.link_capacity_lower =
2443 DataRate::KilobitsPerSec(proto.link_capacity_lower_kbps());
2444 }
2445
2446 absl::optional<uint64_t> base_link_capacity_upper_kbps;
2447 if (proto.has_link_capacity_upper_kbps()) {
2448 base_link_capacity_upper_kbps = proto.link_capacity_upper_kbps();
2449 base_event.link_capacity_upper =
2450 DataRate::KilobitsPerSec(proto.link_capacity_upper_kbps());
2451 }
2452
2453 remote_estimate_events_.push_back(base_event);
2454
2455 const size_t number_of_deltas =
2456 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2457 if (number_of_deltas == 0) {
2458 return ParseStatus::Success();
2459 }
2460
2461 // timestamp_ms
2462 auto timestamp_ms_values =
2463 DecodeDeltas(proto.timestamp_ms_deltas(),
2464 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2465 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2466
2467 // link_capacity_lower_kbps
2468 auto link_capacity_lower_kbps_values =
2469 DecodeDeltas(proto.link_capacity_lower_kbps_deltas(),
2470 base_link_capacity_lower_kbps, number_of_deltas);
2471 RTC_PARSE_CHECK_OR_RETURN_EQ(link_capacity_lower_kbps_values.size(),
2472 number_of_deltas);
2473
2474 // link_capacity_upper_kbps
2475 auto link_capacity_upper_kbps_values =
2476 DecodeDeltas(proto.link_capacity_upper_kbps_deltas(),
2477 base_link_capacity_upper_kbps, number_of_deltas);
2478 RTC_PARSE_CHECK_OR_RETURN_EQ(link_capacity_upper_kbps_values.size(),
2479 number_of_deltas);
2480
2481 // Delta decoding
2482 for (size_t i = 0; i < number_of_deltas; ++i) {
2483 LoggedRemoteEstimateEvent event;
2484 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
2485 event.timestamp_ms = *timestamp_ms_values[i];
2486 if (link_capacity_lower_kbps_values[i])
2487 event.link_capacity_lower =
2488 DataRate::KilobitsPerSec(*link_capacity_lower_kbps_values[i]);
2489 if (link_capacity_upper_kbps_values[i])
2490 event.link_capacity_upper =
2491 DataRate::KilobitsPerSec(*link_capacity_upper_kbps_values[i]);
2492 remote_estimate_events_.push_back(event);
2493 }
2494 return ParseStatus::Success();
2495 }
2496
StoreAudioPlayoutEvent(const rtclog2::AudioPlayoutEvents & proto)2497 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioPlayoutEvent(
2498 const rtclog2::AudioPlayoutEvents& proto) {
2499 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2500 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
2501
2502 // Base event
2503 auto map_it = audio_playout_events_[proto.local_ssrc()];
2504 audio_playout_events_[proto.local_ssrc()].emplace_back(
2505 1000 * proto.timestamp_ms(), proto.local_ssrc());
2506
2507 const size_t number_of_deltas =
2508 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2509 if (number_of_deltas == 0) {
2510 return ParseStatus::Success();
2511 }
2512
2513 // timestamp_ms
2514 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2515 DecodeDeltas(proto.timestamp_ms_deltas(),
2516 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2517 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2518
2519 // local_ssrc
2520 std::vector<absl::optional<uint64_t>> local_ssrc_values = DecodeDeltas(
2521 proto.local_ssrc_deltas(), proto.local_ssrc(), number_of_deltas);
2522 RTC_PARSE_CHECK_OR_RETURN_EQ(local_ssrc_values.size(), number_of_deltas);
2523
2524 // Delta decoding
2525 for (size_t i = 0; i < number_of_deltas; ++i) {
2526 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
2527 RTC_PARSE_CHECK_OR_RETURN(local_ssrc_values[i].has_value());
2528 RTC_PARSE_CHECK_OR_RETURN_LE(local_ssrc_values[i].value(),
2529 std::numeric_limits<uint32_t>::max());
2530
2531 int64_t timestamp_ms;
2532 RTC_PARSE_CHECK_OR_RETURN(
2533 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2534
2535 const uint32_t local_ssrc =
2536 static_cast<uint32_t>(local_ssrc_values[i].value());
2537 audio_playout_events_[local_ssrc].emplace_back(1000 * timestamp_ms,
2538 local_ssrc);
2539 }
2540 return ParseStatus::Success();
2541 }
2542
StoreIncomingRtpPackets(const rtclog2::IncomingRtpPackets & proto)2543 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIncomingRtpPackets(
2544 const rtclog2::IncomingRtpPackets& proto) {
2545 return StoreRtpPackets(proto, &incoming_rtp_packets_map_);
2546 }
2547
StoreOutgoingRtpPackets(const rtclog2::OutgoingRtpPackets & proto)2548 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreOutgoingRtpPackets(
2549 const rtclog2::OutgoingRtpPackets& proto) {
2550 return StoreRtpPackets(proto, &outgoing_rtp_packets_map_);
2551 }
2552
StoreIncomingRtcpPackets(const rtclog2::IncomingRtcpPackets & proto)2553 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIncomingRtcpPackets(
2554 const rtclog2::IncomingRtcpPackets& proto) {
2555 return StoreRtcpPackets(proto, &incoming_rtcp_packets_,
2556 /*remove_duplicates=*/true);
2557 }
2558
StoreOutgoingRtcpPackets(const rtclog2::OutgoingRtcpPackets & proto)2559 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreOutgoingRtcpPackets(
2560 const rtclog2::OutgoingRtcpPackets& proto) {
2561 return StoreRtcpPackets(proto, &outgoing_rtcp_packets_,
2562 /*remove_duplicates=*/false);
2563 }
2564
StoreStartEvent(const rtclog2::BeginLogEvent & proto)2565 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreStartEvent(
2566 const rtclog2::BeginLogEvent& proto) {
2567 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2568 RTC_PARSE_CHECK_OR_RETURN(proto.has_version());
2569 RTC_PARSE_CHECK_OR_RETURN(proto.has_utc_time_ms());
2570 RTC_PARSE_CHECK_OR_RETURN_EQ(proto.version(), 2);
2571 LoggedStartEvent start_event(proto.timestamp_ms() * 1000,
2572 proto.utc_time_ms());
2573
2574 start_log_events_.push_back(start_event);
2575 return ParseStatus::Success();
2576 }
2577
StoreStopEvent(const rtclog2::EndLogEvent & proto)2578 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreStopEvent(
2579 const rtclog2::EndLogEvent& proto) {
2580 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2581 LoggedStopEvent stop_event(proto.timestamp_ms() * 1000);
2582
2583 stop_log_events_.push_back(stop_event);
2584 return ParseStatus::Success();
2585 }
2586
StoreBweLossBasedUpdate(const rtclog2::LossBasedBweUpdates & proto)2587 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweLossBasedUpdate(
2588 const rtclog2::LossBasedBweUpdates& proto) {
2589 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2590 RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
2591 RTC_PARSE_CHECK_OR_RETURN(proto.has_fraction_loss());
2592 RTC_PARSE_CHECK_OR_RETURN(proto.has_total_packets());
2593
2594 // Base event
2595 bwe_loss_updates_.emplace_back(1000 * proto.timestamp_ms(),
2596 proto.bitrate_bps(), proto.fraction_loss(),
2597 proto.total_packets());
2598
2599 const size_t number_of_deltas =
2600 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2601 if (number_of_deltas == 0) {
2602 return ParseStatus::Success();
2603 }
2604
2605 // timestamp_ms
2606 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2607 DecodeDeltas(proto.timestamp_ms_deltas(),
2608 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2609 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2610
2611 // bitrate_bps
2612 std::vector<absl::optional<uint64_t>> bitrate_bps_values = DecodeDeltas(
2613 proto.bitrate_bps_deltas(), proto.bitrate_bps(), number_of_deltas);
2614 RTC_PARSE_CHECK_OR_RETURN_EQ(bitrate_bps_values.size(), number_of_deltas);
2615
2616 // fraction_loss
2617 std::vector<absl::optional<uint64_t>> fraction_loss_values = DecodeDeltas(
2618 proto.fraction_loss_deltas(), proto.fraction_loss(), number_of_deltas);
2619 RTC_PARSE_CHECK_OR_RETURN_EQ(fraction_loss_values.size(), number_of_deltas);
2620
2621 // total_packets
2622 std::vector<absl::optional<uint64_t>> total_packets_values = DecodeDeltas(
2623 proto.total_packets_deltas(), proto.total_packets(), number_of_deltas);
2624 RTC_PARSE_CHECK_OR_RETURN_EQ(total_packets_values.size(), number_of_deltas);
2625
2626 // Delta decoding
2627 for (size_t i = 0; i < number_of_deltas; ++i) {
2628 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
2629 int64_t timestamp_ms;
2630 RTC_PARSE_CHECK_OR_RETURN(
2631 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2632
2633 RTC_PARSE_CHECK_OR_RETURN(bitrate_bps_values[i].has_value());
2634 RTC_PARSE_CHECK_OR_RETURN_LE(bitrate_bps_values[i].value(),
2635 std::numeric_limits<uint32_t>::max());
2636 const uint32_t bitrate_bps =
2637 static_cast<uint32_t>(bitrate_bps_values[i].value());
2638
2639 RTC_PARSE_CHECK_OR_RETURN(fraction_loss_values[i].has_value());
2640 RTC_PARSE_CHECK_OR_RETURN_LE(fraction_loss_values[i].value(),
2641 std::numeric_limits<uint32_t>::max());
2642 const uint32_t fraction_loss =
2643 static_cast<uint32_t>(fraction_loss_values[i].value());
2644
2645 RTC_PARSE_CHECK_OR_RETURN(total_packets_values[i].has_value());
2646 RTC_PARSE_CHECK_OR_RETURN_LE(total_packets_values[i].value(),
2647 std::numeric_limits<uint32_t>::max());
2648 const uint32_t total_packets =
2649 static_cast<uint32_t>(total_packets_values[i].value());
2650
2651 bwe_loss_updates_.emplace_back(1000 * timestamp_ms, bitrate_bps,
2652 fraction_loss, total_packets);
2653 }
2654 return ParseStatus::Success();
2655 }
2656
StoreBweDelayBasedUpdate(const rtclog2::DelayBasedBweUpdates & proto)2657 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweDelayBasedUpdate(
2658 const rtclog2::DelayBasedBweUpdates& proto) {
2659 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2660 RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
2661 RTC_PARSE_CHECK_OR_RETURN(proto.has_detector_state());
2662
2663 // Base event
2664 const BandwidthUsage base_detector_state =
2665 GetRuntimeDetectorState(proto.detector_state());
2666 bwe_delay_updates_.emplace_back(1000 * proto.timestamp_ms(),
2667 proto.bitrate_bps(), base_detector_state);
2668
2669 const size_t number_of_deltas =
2670 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2671 if (number_of_deltas == 0) {
2672 return ParseStatus::Success();
2673 }
2674
2675 // timestamp_ms
2676 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2677 DecodeDeltas(proto.timestamp_ms_deltas(),
2678 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2679 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2680
2681 // bitrate_bps
2682 std::vector<absl::optional<uint64_t>> bitrate_bps_values = DecodeDeltas(
2683 proto.bitrate_bps_deltas(), proto.bitrate_bps(), number_of_deltas);
2684 RTC_PARSE_CHECK_OR_RETURN_EQ(bitrate_bps_values.size(), number_of_deltas);
2685
2686 // detector_state
2687 std::vector<absl::optional<uint64_t>> detector_state_values = DecodeDeltas(
2688 proto.detector_state_deltas(),
2689 static_cast<uint64_t>(proto.detector_state()), number_of_deltas);
2690 RTC_PARSE_CHECK_OR_RETURN_EQ(detector_state_values.size(), number_of_deltas);
2691
2692 // Delta decoding
2693 for (size_t i = 0; i < number_of_deltas; ++i) {
2694 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
2695 int64_t timestamp_ms;
2696 RTC_PARSE_CHECK_OR_RETURN(
2697 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2698
2699 RTC_PARSE_CHECK_OR_RETURN(bitrate_bps_values[i].has_value());
2700 RTC_PARSE_CHECK_OR_RETURN_LE(bitrate_bps_values[i].value(),
2701 std::numeric_limits<uint32_t>::max());
2702 const uint32_t bitrate_bps =
2703 static_cast<uint32_t>(bitrate_bps_values[i].value());
2704
2705 RTC_PARSE_CHECK_OR_RETURN(detector_state_values[i].has_value());
2706 const auto detector_state =
2707 static_cast<rtclog2::DelayBasedBweUpdates::DetectorState>(
2708 detector_state_values[i].value());
2709
2710 bwe_delay_updates_.emplace_back(1000 * timestamp_ms, bitrate_bps,
2711 GetRuntimeDetectorState(detector_state));
2712 }
2713 return ParseStatus::Success();
2714 }
2715
StoreBweProbeClusterCreated(const rtclog2::BweProbeCluster & proto)2716 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeClusterCreated(
2717 const rtclog2::BweProbeCluster& proto) {
2718 LoggedBweProbeClusterCreatedEvent probe_cluster;
2719 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2720 probe_cluster.timestamp_us = proto.timestamp_ms() * 1000;
2721 RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
2722 probe_cluster.id = proto.id();
2723 RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
2724 probe_cluster.bitrate_bps = proto.bitrate_bps();
2725 RTC_PARSE_CHECK_OR_RETURN(proto.has_min_packets());
2726 probe_cluster.min_packets = proto.min_packets();
2727 RTC_PARSE_CHECK_OR_RETURN(proto.has_min_bytes());
2728 probe_cluster.min_bytes = proto.min_bytes();
2729
2730 bwe_probe_cluster_created_events_.push_back(probe_cluster);
2731
2732 // TODO(terelius): Should we delta encode this event type?
2733 return ParseStatus::Success();
2734 }
2735
StoreBweProbeSuccessEvent(const rtclog2::BweProbeResultSuccess & proto)2736 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeSuccessEvent(
2737 const rtclog2::BweProbeResultSuccess& proto) {
2738 LoggedBweProbeSuccessEvent probe_result;
2739 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2740 probe_result.timestamp_us = proto.timestamp_ms() * 1000;
2741 RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
2742 probe_result.id = proto.id();
2743 RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
2744 probe_result.bitrate_bps = proto.bitrate_bps();
2745
2746 bwe_probe_success_events_.push_back(probe_result);
2747
2748 // TODO(terelius): Should we delta encode this event type?
2749 return ParseStatus::Success();
2750 }
2751
StoreBweProbeFailureEvent(const rtclog2::BweProbeResultFailure & proto)2752 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeFailureEvent(
2753 const rtclog2::BweProbeResultFailure& proto) {
2754 LoggedBweProbeFailureEvent probe_result;
2755 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2756 probe_result.timestamp_us = proto.timestamp_ms() * 1000;
2757 RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
2758 probe_result.id = proto.id();
2759 RTC_PARSE_CHECK_OR_RETURN(proto.has_failure());
2760 probe_result.failure_reason = GetRuntimeProbeFailureReason(proto.failure());
2761
2762 bwe_probe_failure_events_.push_back(probe_result);
2763
2764 // TODO(terelius): Should we delta encode this event type?
2765 return ParseStatus::Success();
2766 }
2767
StoreGenericAckReceivedEvent(const rtclog2::GenericAckReceived & proto)2768 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericAckReceivedEvent(
2769 const rtclog2::GenericAckReceived& proto) {
2770 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2771 RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_number());
2772 RTC_PARSE_CHECK_OR_RETURN(proto.has_acked_packet_number());
2773 // receive_acked_packet_time_ms is optional.
2774
2775 absl::optional<int64_t> base_receive_acked_packet_time_ms;
2776 if (proto.has_receive_acked_packet_time_ms()) {
2777 base_receive_acked_packet_time_ms = proto.receive_acked_packet_time_ms();
2778 }
2779 generic_acks_received_.push_back(
2780 {proto.timestamp_ms() * 1000, proto.packet_number(),
2781 proto.acked_packet_number(), base_receive_acked_packet_time_ms});
2782
2783 const size_t number_of_deltas =
2784 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2785 if (number_of_deltas == 0) {
2786 return ParseStatus::Success();
2787 }
2788
2789 // timestamp_ms
2790 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2791 DecodeDeltas(proto.timestamp_ms_deltas(),
2792 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2793 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2794
2795 // packet_number
2796 std::vector<absl::optional<uint64_t>> packet_number_values =
2797 DecodeDeltas(proto.packet_number_deltas(),
2798 ToUnsigned(proto.packet_number()), number_of_deltas);
2799 RTC_PARSE_CHECK_OR_RETURN_EQ(packet_number_values.size(), number_of_deltas);
2800
2801 // acked_packet_number
2802 std::vector<absl::optional<uint64_t>> acked_packet_number_values =
2803 DecodeDeltas(proto.acked_packet_number_deltas(),
2804 ToUnsigned(proto.acked_packet_number()), number_of_deltas);
2805 RTC_PARSE_CHECK_OR_RETURN_EQ(acked_packet_number_values.size(),
2806 number_of_deltas);
2807
2808 // optional receive_acked_packet_time_ms
2809 const absl::optional<uint64_t> unsigned_receive_acked_packet_time_ms_base =
2810 proto.has_receive_acked_packet_time_ms()
2811 ? absl::optional<uint64_t>(
2812 ToUnsigned(proto.receive_acked_packet_time_ms()))
2813 : absl::optional<uint64_t>();
2814 std::vector<absl::optional<uint64_t>> receive_acked_packet_time_ms_values =
2815 DecodeDeltas(proto.receive_acked_packet_time_ms_deltas(),
2816 unsigned_receive_acked_packet_time_ms_base,
2817 number_of_deltas);
2818 RTC_PARSE_CHECK_OR_RETURN_EQ(receive_acked_packet_time_ms_values.size(),
2819 number_of_deltas);
2820
2821 for (size_t i = 0; i < number_of_deltas; i++) {
2822 int64_t timestamp_ms;
2823 RTC_PARSE_CHECK_OR_RETURN(
2824 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2825 int64_t packet_number;
2826 RTC_PARSE_CHECK_OR_RETURN(
2827 ToSigned(packet_number_values[i].value(), &packet_number));
2828 int64_t acked_packet_number;
2829 RTC_PARSE_CHECK_OR_RETURN(
2830 ToSigned(acked_packet_number_values[i].value(), &acked_packet_number));
2831 absl::optional<int64_t> receive_acked_packet_time_ms;
2832
2833 if (receive_acked_packet_time_ms_values[i].has_value()) {
2834 int64_t value;
2835 RTC_PARSE_CHECK_OR_RETURN(
2836 ToSigned(receive_acked_packet_time_ms_values[i].value(), &value));
2837 receive_acked_packet_time_ms = value;
2838 }
2839 generic_acks_received_.push_back({timestamp_ms * 1000, packet_number,
2840 acked_packet_number,
2841 receive_acked_packet_time_ms});
2842 }
2843 return ParseStatus::Success();
2844 }
2845
StoreGenericPacketSentEvent(const rtclog2::GenericPacketSent & proto)2846 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericPacketSentEvent(
2847 const rtclog2::GenericPacketSent& proto) {
2848 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2849
2850 // Base event
2851 RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_number());
2852 RTC_PARSE_CHECK_OR_RETURN(proto.has_overhead_length());
2853 RTC_PARSE_CHECK_OR_RETURN(proto.has_payload_length());
2854 RTC_PARSE_CHECK_OR_RETURN(proto.has_padding_length());
2855
2856 generic_packets_sent_.push_back(
2857 {proto.timestamp_ms() * 1000, proto.packet_number(),
2858 static_cast<size_t>(proto.overhead_length()),
2859 static_cast<size_t>(proto.payload_length()),
2860 static_cast<size_t>(proto.padding_length())});
2861
2862 const size_t number_of_deltas =
2863 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2864 if (number_of_deltas == 0) {
2865 return ParseStatus::Success();
2866 }
2867
2868 // timestamp_ms
2869 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2870 DecodeDeltas(proto.timestamp_ms_deltas(),
2871 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2872 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2873
2874 // packet_number
2875 std::vector<absl::optional<uint64_t>> packet_number_values =
2876 DecodeDeltas(proto.packet_number_deltas(),
2877 ToUnsigned(proto.packet_number()), number_of_deltas);
2878 RTC_PARSE_CHECK_OR_RETURN_EQ(packet_number_values.size(), number_of_deltas);
2879
2880 std::vector<absl::optional<uint64_t>> overhead_length_values =
2881 DecodeDeltas(proto.overhead_length_deltas(), proto.overhead_length(),
2882 number_of_deltas);
2883 RTC_PARSE_CHECK_OR_RETURN_EQ(overhead_length_values.size(), number_of_deltas);
2884
2885 std::vector<absl::optional<uint64_t>> payload_length_values =
2886 DecodeDeltas(proto.payload_length_deltas(),
2887 ToUnsigned(proto.payload_length()), number_of_deltas);
2888 RTC_PARSE_CHECK_OR_RETURN_EQ(payload_length_values.size(), number_of_deltas);
2889
2890 std::vector<absl::optional<uint64_t>> padding_length_values =
2891 DecodeDeltas(proto.padding_length_deltas(),
2892 ToUnsigned(proto.padding_length()), number_of_deltas);
2893 RTC_PARSE_CHECK_OR_RETURN_EQ(padding_length_values.size(), number_of_deltas);
2894
2895 for (size_t i = 0; i < number_of_deltas; i++) {
2896 int64_t timestamp_ms;
2897 RTC_PARSE_CHECK_OR_RETURN(
2898 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2899 int64_t packet_number;
2900 RTC_PARSE_CHECK_OR_RETURN(
2901 ToSigned(packet_number_values[i].value(), &packet_number));
2902 RTC_PARSE_CHECK_OR_RETURN(overhead_length_values[i].has_value());
2903 RTC_PARSE_CHECK_OR_RETURN(payload_length_values[i].has_value());
2904 RTC_PARSE_CHECK_OR_RETURN(padding_length_values[i].has_value());
2905 generic_packets_sent_.push_back(
2906 {timestamp_ms * 1000, packet_number,
2907 static_cast<size_t>(overhead_length_values[i].value()),
2908 static_cast<size_t>(payload_length_values[i].value()),
2909 static_cast<size_t>(padding_length_values[i].value())});
2910 }
2911 return ParseStatus::Success();
2912 }
2913
2914 ParsedRtcEventLog::ParseStatus
StoreGenericPacketReceivedEvent(const rtclog2::GenericPacketReceived & proto)2915 ParsedRtcEventLog::StoreGenericPacketReceivedEvent(
2916 const rtclog2::GenericPacketReceived& proto) {
2917 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2918
2919 // Base event
2920 RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_number());
2921 RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_length());
2922
2923 generic_packets_received_.push_back({proto.timestamp_ms() * 1000,
2924 proto.packet_number(),
2925 proto.packet_length()});
2926
2927 const size_t number_of_deltas =
2928 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
2929 if (number_of_deltas == 0) {
2930 return ParseStatus::Success();
2931 }
2932
2933 // timestamp_ms
2934 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
2935 DecodeDeltas(proto.timestamp_ms_deltas(),
2936 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
2937 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
2938
2939 // packet_number
2940 std::vector<absl::optional<uint64_t>> packet_number_values =
2941 DecodeDeltas(proto.packet_number_deltas(),
2942 ToUnsigned(proto.packet_number()), number_of_deltas);
2943 RTC_PARSE_CHECK_OR_RETURN_EQ(packet_number_values.size(), number_of_deltas);
2944
2945 std::vector<absl::optional<uint64_t>> packet_length_values = DecodeDeltas(
2946 proto.packet_length_deltas(), proto.packet_length(), number_of_deltas);
2947 RTC_PARSE_CHECK_OR_RETURN_EQ(packet_length_values.size(), number_of_deltas);
2948
2949 for (size_t i = 0; i < number_of_deltas; i++) {
2950 int64_t timestamp_ms;
2951 RTC_PARSE_CHECK_OR_RETURN(
2952 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
2953 int64_t packet_number;
2954 RTC_PARSE_CHECK_OR_RETURN(
2955 ToSigned(packet_number_values[i].value(), &packet_number));
2956 int32_t packet_length;
2957 RTC_PARSE_CHECK_OR_RETURN(
2958 ToSigned(packet_length_values[i].value(), &packet_length));
2959 generic_packets_received_.push_back(
2960 {timestamp_ms * 1000, packet_number, packet_length});
2961 }
2962 return ParseStatus::Success();
2963 }
2964
2965 ParsedRtcEventLog::ParseStatus
StoreAudioNetworkAdaptationEvent(const rtclog2::AudioNetworkAdaptations & proto)2966 ParsedRtcEventLog::StoreAudioNetworkAdaptationEvent(
2967 const rtclog2::AudioNetworkAdaptations& proto) {
2968 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
2969
2970 // Base event
2971 {
2972 AudioEncoderRuntimeConfig runtime_config;
2973 if (proto.has_bitrate_bps()) {
2974 runtime_config.bitrate_bps = proto.bitrate_bps();
2975 }
2976 if (proto.has_frame_length_ms()) {
2977 runtime_config.frame_length_ms = proto.frame_length_ms();
2978 }
2979 if (proto.has_uplink_packet_loss_fraction()) {
2980 float uplink_packet_loss_fraction;
2981 RTC_PARSE_CHECK_OR_RETURN(ParsePacketLossFractionFromProtoFormat(
2982 proto.uplink_packet_loss_fraction(), &uplink_packet_loss_fraction));
2983 runtime_config.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
2984 }
2985 if (proto.has_enable_fec()) {
2986 runtime_config.enable_fec = proto.enable_fec();
2987 }
2988 if (proto.has_enable_dtx()) {
2989 runtime_config.enable_dtx = proto.enable_dtx();
2990 }
2991 if (proto.has_num_channels()) {
2992 // Note: Encoding N as N-1 only done for |num_channels_deltas|.
2993 runtime_config.num_channels = proto.num_channels();
2994 }
2995 audio_network_adaptation_events_.emplace_back(1000 * proto.timestamp_ms(),
2996 runtime_config);
2997 }
2998
2999 const size_t number_of_deltas =
3000 proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
3001 if (number_of_deltas == 0) {
3002 return ParseStatus::Success();
3003 }
3004
3005 // timestamp_ms
3006 std::vector<absl::optional<uint64_t>> timestamp_ms_values =
3007 DecodeDeltas(proto.timestamp_ms_deltas(),
3008 ToUnsigned(proto.timestamp_ms()), number_of_deltas);
3009 RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
3010
3011 // bitrate_bps
3012 const absl::optional<uint64_t> unsigned_base_bitrate_bps =
3013 proto.has_bitrate_bps()
3014 ? absl::optional<uint64_t>(ToUnsigned(proto.bitrate_bps()))
3015 : absl::optional<uint64_t>();
3016 std::vector<absl::optional<uint64_t>> bitrate_bps_values = DecodeDeltas(
3017 proto.bitrate_bps_deltas(), unsigned_base_bitrate_bps, number_of_deltas);
3018 RTC_PARSE_CHECK_OR_RETURN_EQ(bitrate_bps_values.size(), number_of_deltas);
3019
3020 // frame_length_ms
3021 const absl::optional<uint64_t> unsigned_base_frame_length_ms =
3022 proto.has_frame_length_ms()
3023 ? absl::optional<uint64_t>(ToUnsigned(proto.frame_length_ms()))
3024 : absl::optional<uint64_t>();
3025 std::vector<absl::optional<uint64_t>> frame_length_ms_values =
3026 DecodeDeltas(proto.frame_length_ms_deltas(),
3027 unsigned_base_frame_length_ms, number_of_deltas);
3028 RTC_PARSE_CHECK_OR_RETURN_EQ(frame_length_ms_values.size(), number_of_deltas);
3029
3030 // uplink_packet_loss_fraction
3031 const absl::optional<uint64_t> uplink_packet_loss_fraction =
3032 proto.has_uplink_packet_loss_fraction()
3033 ? absl::optional<uint64_t>(proto.uplink_packet_loss_fraction())
3034 : absl::optional<uint64_t>();
3035 std::vector<absl::optional<uint64_t>> uplink_packet_loss_fraction_values =
3036 DecodeDeltas(proto.uplink_packet_loss_fraction_deltas(),
3037 uplink_packet_loss_fraction, number_of_deltas);
3038 RTC_PARSE_CHECK_OR_RETURN_EQ(uplink_packet_loss_fraction_values.size(),
3039 number_of_deltas);
3040
3041 // enable_fec
3042 const absl::optional<uint64_t> enable_fec =
3043 proto.has_enable_fec() ? absl::optional<uint64_t>(proto.enable_fec())
3044 : absl::optional<uint64_t>();
3045 std::vector<absl::optional<uint64_t>> enable_fec_values =
3046 DecodeDeltas(proto.enable_fec_deltas(), enable_fec, number_of_deltas);
3047 RTC_PARSE_CHECK_OR_RETURN_EQ(enable_fec_values.size(), number_of_deltas);
3048
3049 // enable_dtx
3050 const absl::optional<uint64_t> enable_dtx =
3051 proto.has_enable_dtx() ? absl::optional<uint64_t>(proto.enable_dtx())
3052 : absl::optional<uint64_t>();
3053 std::vector<absl::optional<uint64_t>> enable_dtx_values =
3054 DecodeDeltas(proto.enable_dtx_deltas(), enable_dtx, number_of_deltas);
3055 RTC_PARSE_CHECK_OR_RETURN_EQ(enable_dtx_values.size(), number_of_deltas);
3056
3057 // num_channels
3058 // Note: For delta encoding, all num_channel values, including the base,
3059 // were shifted down by one, but in the base event, they were not.
3060 // We likewise shift the base event down by one, to get the same base as
3061 // encoding had, but then shift all of the values (except the base) back up
3062 // to their original value.
3063 absl::optional<uint64_t> shifted_base_num_channels;
3064 if (proto.has_num_channels()) {
3065 shifted_base_num_channels =
3066 absl::optional<uint64_t>(proto.num_channels() - 1);
3067 }
3068 std::vector<absl::optional<uint64_t>> num_channels_values = DecodeDeltas(
3069 proto.num_channels_deltas(), shifted_base_num_channels, number_of_deltas);
3070 for (size_t i = 0; i < num_channels_values.size(); ++i) {
3071 if (num_channels_values[i].has_value()) {
3072 num_channels_values[i] = num_channels_values[i].value() + 1;
3073 }
3074 }
3075 RTC_PARSE_CHECK_OR_RETURN_EQ(num_channels_values.size(), number_of_deltas);
3076
3077 // Delta decoding
3078 for (size_t i = 0; i < number_of_deltas; ++i) {
3079 RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
3080 int64_t timestamp_ms;
3081 RTC_PARSE_CHECK_OR_RETURN(
3082 ToSigned(timestamp_ms_values[i].value(), ×tamp_ms));
3083
3084 AudioEncoderRuntimeConfig runtime_config;
3085 if (bitrate_bps_values[i].has_value()) {
3086 int signed_bitrate_bps;
3087 RTC_PARSE_CHECK_OR_RETURN(
3088 ToSigned(bitrate_bps_values[i].value(), &signed_bitrate_bps));
3089 runtime_config.bitrate_bps = signed_bitrate_bps;
3090 }
3091 if (frame_length_ms_values[i].has_value()) {
3092 int signed_frame_length_ms;
3093 RTC_PARSE_CHECK_OR_RETURN(
3094 ToSigned(frame_length_ms_values[i].value(), &signed_frame_length_ms));
3095 runtime_config.frame_length_ms = signed_frame_length_ms;
3096 }
3097 if (uplink_packet_loss_fraction_values[i].has_value()) {
3098 float uplink_packet_loss_fraction;
3099 RTC_PARSE_CHECK_OR_RETURN(ParsePacketLossFractionFromProtoFormat(
3100 rtc::checked_cast<uint32_t>(
3101 uplink_packet_loss_fraction_values[i].value()),
3102 &uplink_packet_loss_fraction));
3103 runtime_config.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
3104 }
3105 if (enable_fec_values[i].has_value()) {
3106 runtime_config.enable_fec =
3107 rtc::checked_cast<bool>(enable_fec_values[i].value());
3108 }
3109 if (enable_dtx_values[i].has_value()) {
3110 runtime_config.enable_dtx =
3111 rtc::checked_cast<bool>(enable_dtx_values[i].value());
3112 }
3113 if (num_channels_values[i].has_value()) {
3114 runtime_config.num_channels =
3115 rtc::checked_cast<size_t>(num_channels_values[i].value());
3116 }
3117 audio_network_adaptation_events_.emplace_back(1000 * timestamp_ms,
3118 runtime_config);
3119 }
3120 return ParseStatus::Success();
3121 }
3122
StoreDtlsTransportState(const rtclog2::DtlsTransportStateEvent & proto)3123 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreDtlsTransportState(
3124 const rtclog2::DtlsTransportStateEvent& proto) {
3125 LoggedDtlsTransportState dtls_state;
3126 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3127 dtls_state.timestamp_us = proto.timestamp_ms() * 1000;
3128
3129 RTC_PARSE_CHECK_OR_RETURN(proto.has_dtls_transport_state());
3130 dtls_state.dtls_transport_state =
3131 GetRuntimeDtlsTransportState(proto.dtls_transport_state());
3132
3133 dtls_transport_states_.push_back(dtls_state);
3134 return ParseStatus::Success();
3135 }
3136
StoreDtlsWritableState(const rtclog2::DtlsWritableState & proto)3137 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreDtlsWritableState(
3138 const rtclog2::DtlsWritableState& proto) {
3139 LoggedDtlsWritableState dtls_writable_state;
3140 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3141 dtls_writable_state.timestamp_us = proto.timestamp_ms() * 1000;
3142 RTC_PARSE_CHECK_OR_RETURN(proto.has_writable());
3143 dtls_writable_state.writable = proto.writable();
3144
3145 dtls_writable_states_.push_back(dtls_writable_state);
3146 return ParseStatus::Success();
3147 }
3148
StoreIceCandidatePairConfig(const rtclog2::IceCandidatePairConfig & proto)3149 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidatePairConfig(
3150 const rtclog2::IceCandidatePairConfig& proto) {
3151 LoggedIceCandidatePairConfig ice_config;
3152 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3153 ice_config.timestamp_us = proto.timestamp_ms() * 1000;
3154
3155 RTC_PARSE_CHECK_OR_RETURN(proto.has_config_type());
3156 ice_config.type = GetRuntimeIceCandidatePairConfigType(proto.config_type());
3157 RTC_PARSE_CHECK_OR_RETURN(proto.has_candidate_pair_id());
3158 ice_config.candidate_pair_id = proto.candidate_pair_id();
3159 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_candidate_type());
3160 ice_config.local_candidate_type =
3161 GetRuntimeIceCandidateType(proto.local_candidate_type());
3162 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_relay_protocol());
3163 ice_config.local_relay_protocol =
3164 GetRuntimeIceCandidatePairProtocol(proto.local_relay_protocol());
3165 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_network_type());
3166 ice_config.local_network_type =
3167 GetRuntimeIceCandidateNetworkType(proto.local_network_type());
3168 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_address_family());
3169 ice_config.local_address_family =
3170 GetRuntimeIceCandidatePairAddressFamily(proto.local_address_family());
3171 RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_candidate_type());
3172 ice_config.remote_candidate_type =
3173 GetRuntimeIceCandidateType(proto.remote_candidate_type());
3174 RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_address_family());
3175 ice_config.remote_address_family =
3176 GetRuntimeIceCandidatePairAddressFamily(proto.remote_address_family());
3177 RTC_PARSE_CHECK_OR_RETURN(proto.has_candidate_pair_protocol());
3178 ice_config.candidate_pair_protocol =
3179 GetRuntimeIceCandidatePairProtocol(proto.candidate_pair_protocol());
3180
3181 ice_candidate_pair_configs_.push_back(ice_config);
3182
3183 // TODO(terelius): Should we delta encode this event type?
3184 return ParseStatus::Success();
3185 }
3186
StoreIceCandidateEvent(const rtclog2::IceCandidatePairEvent & proto)3187 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidateEvent(
3188 const rtclog2::IceCandidatePairEvent& proto) {
3189 LoggedIceCandidatePairEvent ice_event;
3190 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3191 ice_event.timestamp_us = proto.timestamp_ms() * 1000;
3192 RTC_PARSE_CHECK_OR_RETURN(proto.has_event_type());
3193 ice_event.type = GetRuntimeIceCandidatePairEventType(proto.event_type());
3194 RTC_PARSE_CHECK_OR_RETURN(proto.has_candidate_pair_id());
3195 ice_event.candidate_pair_id = proto.candidate_pair_id();
3196 // TODO(zstein): Make the transaction_id field required once all old versions
3197 // of the log (which don't have the field) are obsolete.
3198 ice_event.transaction_id =
3199 proto.has_transaction_id() ? proto.transaction_id() : 0;
3200
3201 ice_candidate_pair_events_.push_back(ice_event);
3202
3203 // TODO(terelius): Should we delta encode this event type?
3204 return ParseStatus::Success();
3205 }
3206
StoreVideoRecvConfig(const rtclog2::VideoRecvStreamConfig & proto)3207 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreVideoRecvConfig(
3208 const rtclog2::VideoRecvStreamConfig& proto) {
3209 LoggedVideoRecvConfig stream;
3210 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3211 stream.timestamp_us = proto.timestamp_ms() * 1000;
3212 RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_ssrc());
3213 stream.config.remote_ssrc = proto.remote_ssrc();
3214 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
3215 stream.config.local_ssrc = proto.local_ssrc();
3216 if (proto.has_rtx_ssrc()) {
3217 stream.config.rtx_ssrc = proto.rtx_ssrc();
3218 }
3219 if (proto.has_header_extensions()) {
3220 stream.config.rtp_extensions =
3221 GetRuntimeRtpHeaderExtensionConfig(proto.header_extensions());
3222 }
3223 video_recv_configs_.push_back(stream);
3224 return ParseStatus::Success();
3225 }
3226
StoreVideoSendConfig(const rtclog2::VideoSendStreamConfig & proto)3227 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreVideoSendConfig(
3228 const rtclog2::VideoSendStreamConfig& proto) {
3229 LoggedVideoSendConfig stream;
3230 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3231 stream.timestamp_us = proto.timestamp_ms() * 1000;
3232 RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
3233 stream.config.local_ssrc = proto.ssrc();
3234 if (proto.has_rtx_ssrc()) {
3235 stream.config.rtx_ssrc = proto.rtx_ssrc();
3236 }
3237 if (proto.has_header_extensions()) {
3238 stream.config.rtp_extensions =
3239 GetRuntimeRtpHeaderExtensionConfig(proto.header_extensions());
3240 }
3241 video_send_configs_.push_back(stream);
3242 return ParseStatus::Success();
3243 }
3244
StoreAudioRecvConfig(const rtclog2::AudioRecvStreamConfig & proto)3245 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioRecvConfig(
3246 const rtclog2::AudioRecvStreamConfig& proto) {
3247 LoggedAudioRecvConfig stream;
3248 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3249 stream.timestamp_us = proto.timestamp_ms() * 1000;
3250 RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_ssrc());
3251 stream.config.remote_ssrc = proto.remote_ssrc();
3252 RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
3253 stream.config.local_ssrc = proto.local_ssrc();
3254 if (proto.has_header_extensions()) {
3255 stream.config.rtp_extensions =
3256 GetRuntimeRtpHeaderExtensionConfig(proto.header_extensions());
3257 }
3258 audio_recv_configs_.push_back(stream);
3259 return ParseStatus::Success();
3260 }
3261
StoreAudioSendConfig(const rtclog2::AudioSendStreamConfig & proto)3262 ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioSendConfig(
3263 const rtclog2::AudioSendStreamConfig& proto) {
3264 LoggedAudioSendConfig stream;
3265 RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
3266 stream.timestamp_us = proto.timestamp_ms() * 1000;
3267 RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
3268 stream.config.local_ssrc = proto.ssrc();
3269 if (proto.has_header_extensions()) {
3270 stream.config.rtp_extensions =
3271 GetRuntimeRtpHeaderExtensionConfig(proto.header_extensions());
3272 }
3273 audio_send_configs_.push_back(stream);
3274 return ParseStatus::Success();
3275 }
3276
3277 } // namespace webrtc
3278