1 /*
2 * Copyright (c) 2017 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/encoder/rtc_event_log_encoder_new_format.h"
12
13 #include "absl/types/optional.h"
14 #include "api/array_view.h"
15 #include "api/network_state_predictor.h"
16 #include "logging/rtc_event_log/encoder/blob_encoding.h"
17 #include "logging/rtc_event_log/encoder/delta_encoding.h"
18 #include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
19 #include "logging/rtc_event_log/events/rtc_event_alr_state.h"
20 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
21 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
22 #include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
23 #include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
24 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
25 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
26 #include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
27 #include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
28 #include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
29 #include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
30 #include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
31 #include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
32 #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
33 #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
34 #include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
35 #include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
36 #include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
37 #include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
38 #include "logging/rtc_event_log/events/rtc_event_route_change.h"
39 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
40 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
41 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
42 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
43 #include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
44 #include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
45 #include "logging/rtc_event_log/rtc_stream_config.h"
46 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
47 #include "modules/rtp_rtcp/include/rtp_cvo.h"
48 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
49 #include "modules/rtp_rtcp/source/rtcp_packet/app.h"
50 #include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
51 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
52 #include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
53 #include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
54 #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
55 #include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h"
56 #include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
57 #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
58 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
59 #include "modules/rtp_rtcp/source/rtp_packet.h"
60 #include "rtc_base/checks.h"
61 #include "rtc_base/ignore_wundef.h"
62 #include "rtc_base/logging.h"
63
64 // *.pb.h files are generated at build-time by the protobuf compiler.
65 RTC_PUSH_IGNORING_WUNDEF()
66 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
67 #include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log2.pb.h"
68 #else
69 #include "logging/rtc_event_log/rtc_event_log2.pb.h"
70 #endif
71 RTC_POP_IGNORING_WUNDEF()
72
73 using webrtc_event_logging::ToUnsigned;
74
75 namespace webrtc {
76
77 namespace {
ConvertToProtoFormat(BandwidthUsage state)78 rtclog2::DelayBasedBweUpdates::DetectorState ConvertToProtoFormat(
79 BandwidthUsage state) {
80 switch (state) {
81 case BandwidthUsage::kBwNormal:
82 return rtclog2::DelayBasedBweUpdates::BWE_NORMAL;
83 case BandwidthUsage::kBwUnderusing:
84 return rtclog2::DelayBasedBweUpdates::BWE_UNDERUSING;
85 case BandwidthUsage::kBwOverusing:
86 return rtclog2::DelayBasedBweUpdates::BWE_OVERUSING;
87 case BandwidthUsage::kLast:
88 RTC_DCHECK_NOTREACHED();
89 }
90 RTC_DCHECK_NOTREACHED();
91 return rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE;
92 }
93
ConvertToProtoFormat(VideoCodecType codec)94 rtclog2::FrameDecodedEvents::Codec ConvertToProtoFormat(VideoCodecType codec) {
95 switch (codec) {
96 case VideoCodecType::kVideoCodecGeneric:
97 return rtclog2::FrameDecodedEvents::CODEC_GENERIC;
98 case VideoCodecType::kVideoCodecVP8:
99 return rtclog2::FrameDecodedEvents::CODEC_VP8;
100 case VideoCodecType::kVideoCodecVP9:
101 return rtclog2::FrameDecodedEvents::CODEC_VP9;
102 case VideoCodecType::kVideoCodecAV1:
103 return rtclog2::FrameDecodedEvents::CODEC_AV1;
104 case VideoCodecType::kVideoCodecH264:
105 return rtclog2::FrameDecodedEvents::CODEC_H264;
106 case VideoCodecType::kVideoCodecMultiplex:
107 // This codec type is afaik not used.
108 return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
109 }
110 RTC_DCHECK_NOTREACHED();
111 return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
112 }
113
ConvertToProtoFormat(ProbeFailureReason failure_reason)114 rtclog2::BweProbeResultFailure::FailureReason ConvertToProtoFormat(
115 ProbeFailureReason failure_reason) {
116 switch (failure_reason) {
117 case ProbeFailureReason::kInvalidSendReceiveInterval:
118 return rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_INTERVAL;
119 case ProbeFailureReason::kInvalidSendReceiveRatio:
120 return rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_RATIO;
121 case ProbeFailureReason::kTimeout:
122 return rtclog2::BweProbeResultFailure::TIMEOUT;
123 case ProbeFailureReason::kLast:
124 RTC_DCHECK_NOTREACHED();
125 }
126 RTC_DCHECK_NOTREACHED();
127 return rtclog2::BweProbeResultFailure::UNKNOWN;
128 }
129
130 // Returns true if there are recognized extensions that we should log
131 // and false if there are no extensions or all extensions are types we don't
132 // log. The protobuf representation of the header configs is written to
133 // `proto_config`.
ConvertToProtoFormat(const std::vector<RtpExtension> & extensions,rtclog2::RtpHeaderExtensionConfig * proto_config)134 bool ConvertToProtoFormat(const std::vector<RtpExtension>& extensions,
135 rtclog2::RtpHeaderExtensionConfig* proto_config) {
136 size_t unknown_extensions = 0;
137 for (auto& extension : extensions) {
138 if (extension.uri == RtpExtension::kAudioLevelUri) {
139 proto_config->set_audio_level_id(extension.id);
140 } else if (extension.uri == RtpExtension::kTimestampOffsetUri) {
141 proto_config->set_transmission_time_offset_id(extension.id);
142 } else if (extension.uri == RtpExtension::kAbsSendTimeUri) {
143 proto_config->set_absolute_send_time_id(extension.id);
144 } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
145 proto_config->set_transport_sequence_number_id(extension.id);
146 } else if (extension.uri == RtpExtension::kVideoRotationUri) {
147 proto_config->set_video_rotation_id(extension.id);
148 } else {
149 ++unknown_extensions;
150 }
151 }
152 return unknown_extensions < extensions.size();
153 }
154
ConvertToProtoFormat(webrtc::DtlsTransportState state)155 rtclog2::DtlsTransportStateEvent::DtlsTransportState ConvertToProtoFormat(
156 webrtc::DtlsTransportState state) {
157 switch (state) {
158 case webrtc::DtlsTransportState::kNew:
159 return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_NEW;
160 case webrtc::DtlsTransportState::kConnecting:
161 return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTING;
162 case webrtc::DtlsTransportState::kConnected:
163 return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTED;
164 case webrtc::DtlsTransportState::kClosed:
165 return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CLOSED;
166 case webrtc::DtlsTransportState::kFailed:
167 return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_FAILED;
168 case webrtc::DtlsTransportState::kNumValues:
169 RTC_DCHECK_NOTREACHED();
170 }
171 RTC_DCHECK_NOTREACHED();
172 return rtclog2::DtlsTransportStateEvent::UNKNOWN_DTLS_TRANSPORT_STATE;
173 }
174
175 rtclog2::IceCandidatePairConfig::IceCandidatePairConfigType
ConvertToProtoFormat(IceCandidatePairConfigType type)176 ConvertToProtoFormat(IceCandidatePairConfigType type) {
177 switch (type) {
178 case IceCandidatePairConfigType::kAdded:
179 return rtclog2::IceCandidatePairConfig::ADDED;
180 case IceCandidatePairConfigType::kUpdated:
181 return rtclog2::IceCandidatePairConfig::UPDATED;
182 case IceCandidatePairConfigType::kDestroyed:
183 return rtclog2::IceCandidatePairConfig::DESTROYED;
184 case IceCandidatePairConfigType::kSelected:
185 return rtclog2::IceCandidatePairConfig::SELECTED;
186 case IceCandidatePairConfigType::kNumValues:
187 RTC_DCHECK_NOTREACHED();
188 }
189 RTC_DCHECK_NOTREACHED();
190 return rtclog2::IceCandidatePairConfig::UNKNOWN_CONFIG_TYPE;
191 }
192
ConvertToProtoFormat(IceCandidateType type)193 rtclog2::IceCandidatePairConfig::IceCandidateType ConvertToProtoFormat(
194 IceCandidateType type) {
195 switch (type) {
196 case IceCandidateType::kUnknown:
197 return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
198 case IceCandidateType::kLocal:
199 return rtclog2::IceCandidatePairConfig::LOCAL;
200 case IceCandidateType::kStun:
201 return rtclog2::IceCandidatePairConfig::STUN;
202 case IceCandidateType::kPrflx:
203 return rtclog2::IceCandidatePairConfig::PRFLX;
204 case IceCandidateType::kRelay:
205 return rtclog2::IceCandidatePairConfig::RELAY;
206 case IceCandidateType::kNumValues:
207 RTC_DCHECK_NOTREACHED();
208 }
209 RTC_DCHECK_NOTREACHED();
210 return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
211 }
212
ConvertToProtoFormat(IceCandidatePairProtocol protocol)213 rtclog2::IceCandidatePairConfig::Protocol ConvertToProtoFormat(
214 IceCandidatePairProtocol protocol) {
215 switch (protocol) {
216 case IceCandidatePairProtocol::kUnknown:
217 return rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
218 case IceCandidatePairProtocol::kUdp:
219 return rtclog2::IceCandidatePairConfig::UDP;
220 case IceCandidatePairProtocol::kTcp:
221 return rtclog2::IceCandidatePairConfig::TCP;
222 case IceCandidatePairProtocol::kSsltcp:
223 return rtclog2::IceCandidatePairConfig::SSLTCP;
224 case IceCandidatePairProtocol::kTls:
225 return rtclog2::IceCandidatePairConfig::TLS;
226 case IceCandidatePairProtocol::kNumValues:
227 RTC_DCHECK_NOTREACHED();
228 }
229 RTC_DCHECK_NOTREACHED();
230 return rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
231 }
232
ConvertToProtoFormat(IceCandidatePairAddressFamily address_family)233 rtclog2::IceCandidatePairConfig::AddressFamily ConvertToProtoFormat(
234 IceCandidatePairAddressFamily address_family) {
235 switch (address_family) {
236 case IceCandidatePairAddressFamily::kUnknown:
237 return rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
238 case IceCandidatePairAddressFamily::kIpv4:
239 return rtclog2::IceCandidatePairConfig::IPV4;
240 case IceCandidatePairAddressFamily::kIpv6:
241 return rtclog2::IceCandidatePairConfig::IPV6;
242 case IceCandidatePairAddressFamily::kNumValues:
243 RTC_DCHECK_NOTREACHED();
244 }
245 RTC_DCHECK_NOTREACHED();
246 return rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
247 }
248
ConvertToProtoFormat(IceCandidateNetworkType network_type)249 rtclog2::IceCandidatePairConfig::NetworkType ConvertToProtoFormat(
250 IceCandidateNetworkType network_type) {
251 switch (network_type) {
252 case IceCandidateNetworkType::kUnknown:
253 return rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
254 case IceCandidateNetworkType::kEthernet:
255 return rtclog2::IceCandidatePairConfig::ETHERNET;
256 case IceCandidateNetworkType::kLoopback:
257 return rtclog2::IceCandidatePairConfig::LOOPBACK;
258 case IceCandidateNetworkType::kWifi:
259 return rtclog2::IceCandidatePairConfig::WIFI;
260 case IceCandidateNetworkType::kVpn:
261 return rtclog2::IceCandidatePairConfig::VPN;
262 case IceCandidateNetworkType::kCellular:
263 return rtclog2::IceCandidatePairConfig::CELLULAR;
264 case IceCandidateNetworkType::kNumValues:
265 RTC_DCHECK_NOTREACHED();
266 }
267 RTC_DCHECK_NOTREACHED();
268 return rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
269 }
270
ConvertToProtoFormat(IceCandidatePairEventType type)271 rtclog2::IceCandidatePairEvent::IceCandidatePairEventType ConvertToProtoFormat(
272 IceCandidatePairEventType type) {
273 switch (type) {
274 case IceCandidatePairEventType::kCheckSent:
275 return rtclog2::IceCandidatePairEvent::CHECK_SENT;
276 case IceCandidatePairEventType::kCheckReceived:
277 return rtclog2::IceCandidatePairEvent::CHECK_RECEIVED;
278 case IceCandidatePairEventType::kCheckResponseSent:
279 return rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_SENT;
280 case IceCandidatePairEventType::kCheckResponseReceived:
281 return rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED;
282 case IceCandidatePairEventType::kNumValues:
283 RTC_DCHECK_NOTREACHED();
284 }
285 RTC_DCHECK_NOTREACHED();
286 return rtclog2::IceCandidatePairEvent::UNKNOWN_CHECK_TYPE;
287 }
288
289 // Copies all RTCP blocks except APP, SDES and unknown from `packet` to
290 // `buffer`. `buffer` must have space for at least `packet.size()` bytes.
RemoveNonAllowlistedRtcpBlocks(const rtc::Buffer & packet,uint8_t * buffer)291 size_t RemoveNonAllowlistedRtcpBlocks(const rtc::Buffer& packet,
292 uint8_t* buffer) {
293 RTC_DCHECK(buffer != nullptr);
294 rtcp::CommonHeader header;
295 const uint8_t* block_begin = packet.data();
296 const uint8_t* packet_end = packet.data() + packet.size();
297 size_t buffer_length = 0;
298 while (block_begin < packet_end) {
299 if (!header.Parse(block_begin, packet_end - block_begin)) {
300 break; // Incorrect message header.
301 }
302 const uint8_t* next_block = header.NextPacket();
303 RTC_DCHECK_GT(next_block, block_begin);
304 RTC_DCHECK_LE(next_block, packet_end);
305 size_t block_size = next_block - block_begin;
306 switch (header.type()) {
307 case rtcp::Bye::kPacketType:
308 case rtcp::ExtendedReports::kPacketType:
309 case rtcp::Psfb::kPacketType:
310 case rtcp::ReceiverReport::kPacketType:
311 case rtcp::Rtpfb::kPacketType:
312 case rtcp::SenderReport::kPacketType:
313 // We log sender reports, receiver reports, bye messages, third-party
314 // loss reports, payload-specific feedback and extended reports.
315 // TODO(terelius): As an optimization, don't copy anything if all blocks
316 // in the packet are allowlisted types.
317 memcpy(buffer + buffer_length, block_begin, block_size);
318 buffer_length += block_size;
319 break;
320 case rtcp::App::kPacketType:
321 case rtcp::Sdes::kPacketType:
322 default:
323 // We don't log sender descriptions, application defined messages
324 // or message blocks of unknown type.
325 break;
326 }
327
328 block_begin += block_size;
329 }
330 return buffer_length;
331 }
332
333 template <typename EventType, typename ProtoType>
EncodeRtcpPacket(rtc::ArrayView<const EventType * > batch,ProtoType * proto_batch)334 void EncodeRtcpPacket(rtc::ArrayView<const EventType*> batch,
335 ProtoType* proto_batch) {
336 if (batch.empty()) {
337 return;
338 }
339
340 // Base event
341 const EventType* const base_event = batch[0];
342 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
343 {
344 std::vector<uint8_t> buffer(base_event->packet().size());
345 size_t buffer_length =
346 RemoveNonAllowlistedRtcpBlocks(base_event->packet(), buffer.data());
347 proto_batch->set_raw_packet(buffer.data(), buffer_length);
348 }
349
350 if (batch.size() == 1) {
351 return;
352 }
353
354 // Delta encoding
355 proto_batch->set_number_of_deltas(batch.size() - 1);
356 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
357 std::string encoded_deltas;
358
359 // timestamp_ms
360 for (size_t i = 0; i < values.size(); ++i) {
361 const EventType* event = batch[i + 1];
362 values[i] = ToUnsigned(event->timestamp_ms());
363 }
364 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
365 if (!encoded_deltas.empty()) {
366 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
367 }
368
369 // raw_packet
370 std::vector<std::string> scrubed_packets(batch.size() - 1);
371 for (size_t i = 0; i < scrubed_packets.size(); ++i) {
372 const EventType* event = batch[i + 1];
373 scrubed_packets[i].resize(event->packet().size());
374 static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "");
375 const size_t buffer_length = RemoveNonAllowlistedRtcpBlocks(
376 event->packet(), reinterpret_cast<uint8_t*>(&scrubed_packets[i][0]));
377 if (buffer_length < event->packet().size()) {
378 scrubed_packets[i].resize(buffer_length);
379 }
380 }
381 proto_batch->set_raw_packet_blobs(EncodeBlobs(scrubed_packets));
382 }
383
384 template <typename EventType, typename ProtoType>
EncodeRtpPacket(const std::vector<const EventType * > & batch,ProtoType * proto_batch)385 void EncodeRtpPacket(const std::vector<const EventType*>& batch,
386 ProtoType* proto_batch) {
387 if (batch.empty()) {
388 return;
389 }
390
391 // Base event
392 const EventType* const base_event = batch[0];
393 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
394 proto_batch->set_marker(base_event->Marker());
395 // TODO(terelius): Is payload type needed?
396 proto_batch->set_payload_type(base_event->PayloadType());
397 proto_batch->set_sequence_number(base_event->SequenceNumber());
398 proto_batch->set_rtp_timestamp(base_event->Timestamp());
399 proto_batch->set_ssrc(base_event->Ssrc());
400 proto_batch->set_payload_size(base_event->payload_length());
401 proto_batch->set_header_size(base_event->header_length());
402 proto_batch->set_padding_size(base_event->padding_length());
403
404 // Add header extensions (base event).
405 absl::optional<uint64_t> base_transport_sequence_number;
406 {
407 uint16_t seqnum;
408 if (base_event->template GetExtension<TransportSequenceNumber>(&seqnum)) {
409 proto_batch->set_transport_sequence_number(seqnum);
410 base_transport_sequence_number = seqnum;
411 }
412 }
413
414 absl::optional<uint64_t> unsigned_base_transmission_time_offset;
415 {
416 int32_t offset;
417 if (base_event->template GetExtension<TransmissionOffset>(&offset)) {
418 proto_batch->set_transmission_time_offset(offset);
419 unsigned_base_transmission_time_offset = ToUnsigned(offset);
420 }
421 }
422
423 absl::optional<uint64_t> base_absolute_send_time;
424 {
425 uint32_t sendtime;
426 if (base_event->template GetExtension<AbsoluteSendTime>(&sendtime)) {
427 proto_batch->set_absolute_send_time(sendtime);
428 base_absolute_send_time = sendtime;
429 }
430 }
431
432 absl::optional<uint64_t> base_video_rotation;
433 {
434 VideoRotation video_rotation;
435 if (base_event->template GetExtension<VideoOrientation>(&video_rotation)) {
436 proto_batch->set_video_rotation(
437 ConvertVideoRotationToCVOByte(video_rotation));
438 base_video_rotation = ConvertVideoRotationToCVOByte(video_rotation);
439 }
440 }
441
442 absl::optional<uint64_t> base_audio_level;
443 absl::optional<uint64_t> base_voice_activity;
444 {
445 bool voice_activity;
446 uint8_t audio_level;
447 if (base_event->template GetExtension<AudioLevel>(&voice_activity,
448 &audio_level)) {
449 RTC_DCHECK_LE(audio_level, 0x7Fu);
450 base_audio_level = audio_level;
451 proto_batch->set_audio_level(audio_level);
452
453 base_voice_activity = voice_activity;
454 proto_batch->set_voice_activity(voice_activity);
455 }
456 }
457
458 if (batch.size() == 1) {
459 return;
460 }
461
462 // Delta encoding
463 proto_batch->set_number_of_deltas(batch.size() - 1);
464 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
465 std::string encoded_deltas;
466
467 // timestamp_ms (event)
468 for (size_t i = 0; i < values.size(); ++i) {
469 const EventType* event = batch[i + 1];
470 values[i] = ToUnsigned(event->timestamp_ms());
471 }
472 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
473 if (!encoded_deltas.empty()) {
474 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
475 }
476
477 // marker (RTP base)
478 for (size_t i = 0; i < values.size(); ++i) {
479 const EventType* event = batch[i + 1];
480 values[i] = event->Marker();
481 }
482 encoded_deltas = EncodeDeltas(base_event->Marker(), values);
483 if (!encoded_deltas.empty()) {
484 proto_batch->set_marker_deltas(encoded_deltas);
485 }
486
487 // payload_type (RTP base)
488 for (size_t i = 0; i < values.size(); ++i) {
489 const EventType* event = batch[i + 1];
490 values[i] = event->PayloadType();
491 }
492 encoded_deltas = EncodeDeltas(base_event->PayloadType(), values);
493 if (!encoded_deltas.empty()) {
494 proto_batch->set_payload_type_deltas(encoded_deltas);
495 }
496
497 // sequence_number (RTP base)
498 for (size_t i = 0; i < values.size(); ++i) {
499 const EventType* event = batch[i + 1];
500 values[i] = event->SequenceNumber();
501 }
502 encoded_deltas = EncodeDeltas(base_event->SequenceNumber(), values);
503 if (!encoded_deltas.empty()) {
504 proto_batch->set_sequence_number_deltas(encoded_deltas);
505 }
506
507 // rtp_timestamp (RTP base)
508 for (size_t i = 0; i < values.size(); ++i) {
509 const EventType* event = batch[i + 1];
510 values[i] = event->Timestamp();
511 }
512 encoded_deltas = EncodeDeltas(base_event->Timestamp(), values);
513 if (!encoded_deltas.empty()) {
514 proto_batch->set_rtp_timestamp_deltas(encoded_deltas);
515 }
516
517 // ssrc (RTP base)
518 for (size_t i = 0; i < values.size(); ++i) {
519 const EventType* event = batch[i + 1];
520 values[i] = event->Ssrc();
521 }
522 encoded_deltas = EncodeDeltas(base_event->Ssrc(), values);
523 if (!encoded_deltas.empty()) {
524 proto_batch->set_ssrc_deltas(encoded_deltas);
525 }
526
527 // payload_size (RTP base)
528 for (size_t i = 0; i < values.size(); ++i) {
529 const EventType* event = batch[i + 1];
530 values[i] = event->payload_length();
531 }
532 encoded_deltas = EncodeDeltas(base_event->payload_length(), values);
533 if (!encoded_deltas.empty()) {
534 proto_batch->set_payload_size_deltas(encoded_deltas);
535 }
536
537 // header_size (RTP base)
538 for (size_t i = 0; i < values.size(); ++i) {
539 const EventType* event = batch[i + 1];
540 values[i] = event->header_length();
541 }
542 encoded_deltas = EncodeDeltas(base_event->header_length(), values);
543 if (!encoded_deltas.empty()) {
544 proto_batch->set_header_size_deltas(encoded_deltas);
545 }
546
547 // padding_size (RTP base)
548 for (size_t i = 0; i < values.size(); ++i) {
549 const EventType* event = batch[i + 1];
550 values[i] = event->padding_length();
551 }
552 encoded_deltas = EncodeDeltas(base_event->padding_length(), values);
553 if (!encoded_deltas.empty()) {
554 proto_batch->set_padding_size_deltas(encoded_deltas);
555 }
556
557 // transport_sequence_number (RTP extension)
558 for (size_t i = 0; i < values.size(); ++i) {
559 const EventType* event = batch[i + 1];
560 uint16_t seqnum;
561 if (event->template GetExtension<TransportSequenceNumber>(&seqnum)) {
562 values[i] = seqnum;
563 } else {
564 values[i].reset();
565 }
566 }
567 encoded_deltas = EncodeDeltas(base_transport_sequence_number, values);
568 if (!encoded_deltas.empty()) {
569 proto_batch->set_transport_sequence_number_deltas(encoded_deltas);
570 }
571
572 // transmission_time_offset (RTP extension)
573 for (size_t i = 0; i < values.size(); ++i) {
574 const EventType* event = batch[i + 1];
575 int32_t offset;
576 if (event->template GetExtension<TransmissionOffset>(&offset)) {
577 values[i] = ToUnsigned(offset);
578 } else {
579 values[i].reset();
580 }
581 }
582 encoded_deltas = EncodeDeltas(unsigned_base_transmission_time_offset, values);
583 if (!encoded_deltas.empty()) {
584 proto_batch->set_transmission_time_offset_deltas(encoded_deltas);
585 }
586
587 // absolute_send_time (RTP extension)
588 for (size_t i = 0; i < values.size(); ++i) {
589 const EventType* event = batch[i + 1];
590 uint32_t sendtime;
591 if (event->template GetExtension<AbsoluteSendTime>(&sendtime)) {
592 values[i] = sendtime;
593 } else {
594 values[i].reset();
595 }
596 }
597 encoded_deltas = EncodeDeltas(base_absolute_send_time, values);
598 if (!encoded_deltas.empty()) {
599 proto_batch->set_absolute_send_time_deltas(encoded_deltas);
600 }
601
602 // video_rotation (RTP extension)
603 for (size_t i = 0; i < values.size(); ++i) {
604 const EventType* event = batch[i + 1];
605 VideoRotation video_rotation;
606 if (event->template GetExtension<VideoOrientation>(&video_rotation)) {
607 values[i] = ConvertVideoRotationToCVOByte(video_rotation);
608 } else {
609 values[i].reset();
610 }
611 }
612 encoded_deltas = EncodeDeltas(base_video_rotation, values);
613 if (!encoded_deltas.empty()) {
614 proto_batch->set_video_rotation_deltas(encoded_deltas);
615 }
616
617 // audio_level (RTP extension)
618 for (size_t i = 0; i < values.size(); ++i) {
619 const EventType* event = batch[i + 1];
620 bool voice_activity;
621 uint8_t audio_level;
622 if (event->template GetExtension<AudioLevel>(&voice_activity,
623 &audio_level)) {
624 RTC_DCHECK_LE(audio_level, 0x7Fu);
625 values[i] = audio_level;
626 } else {
627 values[i].reset();
628 }
629 }
630 encoded_deltas = EncodeDeltas(base_audio_level, values);
631 if (!encoded_deltas.empty()) {
632 proto_batch->set_audio_level_deltas(encoded_deltas);
633 }
634
635 // voice_activity (RTP extension)
636 for (size_t i = 0; i < values.size(); ++i) {
637 const EventType* event = batch[i + 1];
638 bool voice_activity;
639 uint8_t audio_level;
640 if (event->template GetExtension<AudioLevel>(&voice_activity,
641 &audio_level)) {
642 RTC_DCHECK_LE(audio_level, 0x7Fu);
643 values[i] = voice_activity;
644 } else {
645 values[i].reset();
646 }
647 }
648 encoded_deltas = EncodeDeltas(base_voice_activity, values);
649 if (!encoded_deltas.empty()) {
650 proto_batch->set_voice_activity_deltas(encoded_deltas);
651 }
652 }
653 } // namespace
654
EncodeLogStart(int64_t timestamp_us,int64_t utc_time_us)655 std::string RtcEventLogEncoderNewFormat::EncodeLogStart(int64_t timestamp_us,
656 int64_t utc_time_us) {
657 rtclog2::EventStream event_stream;
658 rtclog2::BeginLogEvent* proto_batch = event_stream.add_begin_log_events();
659 proto_batch->set_timestamp_ms(timestamp_us / 1000);
660 proto_batch->set_version(2);
661 proto_batch->set_utc_time_ms(utc_time_us / 1000);
662 return event_stream.SerializeAsString();
663 }
664
EncodeLogEnd(int64_t timestamp_us)665 std::string RtcEventLogEncoderNewFormat::EncodeLogEnd(int64_t timestamp_us) {
666 rtclog2::EventStream event_stream;
667 rtclog2::EndLogEvent* proto_batch = event_stream.add_end_log_events();
668 proto_batch->set_timestamp_ms(timestamp_us / 1000);
669 return event_stream.SerializeAsString();
670 }
671
EncodeBatch(std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,std::deque<std::unique_ptr<RtcEvent>>::const_iterator end)672 std::string RtcEventLogEncoderNewFormat::EncodeBatch(
673 std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
674 std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) {
675 rtclog2::EventStream event_stream;
676 std::string encoded_output;
677
678 {
679 std::vector<const RtcEventAlrState*> alr_state_events;
680 std::vector<const RtcEventAudioNetworkAdaptation*>
681 audio_network_adaptation_events;
682 std::vector<const RtcEventAudioPlayout*> audio_playout_events;
683 std::vector<const RtcEventAudioReceiveStreamConfig*>
684 audio_recv_stream_configs;
685 std::vector<const RtcEventAudioSendStreamConfig*> audio_send_stream_configs;
686 std::vector<const RtcEventBweUpdateDelayBased*> bwe_delay_based_updates;
687 std::vector<const RtcEventBweUpdateLossBased*> bwe_loss_based_updates;
688 std::vector<const RtcEventDtlsTransportState*> dtls_transport_states;
689 std::vector<const RtcEventDtlsWritableState*> dtls_writable_states;
690 std::map<uint32_t /* SSRC */, std::vector<const RtcEventFrameDecoded*>>
691 frames_decoded;
692 std::vector<const RtcEventGenericAckReceived*> generic_acks_received;
693 std::vector<const RtcEventGenericPacketReceived*> generic_packets_received;
694 std::vector<const RtcEventGenericPacketSent*> generic_packets_sent;
695 std::vector<const RtcEventIceCandidatePair*> ice_candidate_events;
696 std::vector<const RtcEventIceCandidatePairConfig*> ice_candidate_configs;
697 std::vector<const RtcEventProbeClusterCreated*>
698 probe_cluster_created_events;
699 std::vector<const RtcEventProbeResultFailure*> probe_result_failure_events;
700 std::vector<const RtcEventProbeResultSuccess*> probe_result_success_events;
701 std::vector<const RtcEventRouteChange*> route_change_events;
702 std::vector<const RtcEventRemoteEstimate*> remote_estimate_events;
703 std::vector<const RtcEventRtcpPacketIncoming*> incoming_rtcp_packets;
704 std::vector<const RtcEventRtcpPacketOutgoing*> outgoing_rtcp_packets;
705 std::map<uint32_t /* SSRC */, std::vector<const RtcEventRtpPacketIncoming*>>
706 incoming_rtp_packets;
707 std::map<uint32_t /* SSRC */, std::vector<const RtcEventRtpPacketOutgoing*>>
708 outgoing_rtp_packets;
709 std::vector<const RtcEventVideoReceiveStreamConfig*>
710 video_recv_stream_configs;
711 std::vector<const RtcEventVideoSendStreamConfig*> video_send_stream_configs;
712
713 for (auto it = begin; it != end; ++it) {
714 switch ((*it)->GetType()) {
715 case RtcEvent::Type::AlrStateEvent: {
716 auto* rtc_event =
717 static_cast<const RtcEventAlrState* const>(it->get());
718 alr_state_events.push_back(rtc_event);
719 break;
720 }
721 case RtcEvent::Type::AudioNetworkAdaptation: {
722 auto* rtc_event =
723 static_cast<const RtcEventAudioNetworkAdaptation* const>(
724 it->get());
725 audio_network_adaptation_events.push_back(rtc_event);
726 break;
727 }
728 case RtcEvent::Type::AudioPlayout: {
729 auto* rtc_event =
730 static_cast<const RtcEventAudioPlayout* const>(it->get());
731 audio_playout_events.push_back(rtc_event);
732 break;
733 }
734 case RtcEvent::Type::AudioReceiveStreamConfig: {
735 auto* rtc_event =
736 static_cast<const RtcEventAudioReceiveStreamConfig* const>(
737 it->get());
738 audio_recv_stream_configs.push_back(rtc_event);
739 break;
740 }
741 case RtcEvent::Type::AudioSendStreamConfig: {
742 auto* rtc_event =
743 static_cast<const RtcEventAudioSendStreamConfig* const>(
744 it->get());
745 audio_send_stream_configs.push_back(rtc_event);
746 break;
747 }
748 case RtcEvent::Type::BweUpdateDelayBased: {
749 auto* rtc_event =
750 static_cast<const RtcEventBweUpdateDelayBased* const>(it->get());
751 bwe_delay_based_updates.push_back(rtc_event);
752 break;
753 }
754 case RtcEvent::Type::BweUpdateLossBased: {
755 auto* rtc_event =
756 static_cast<const RtcEventBweUpdateLossBased* const>(it->get());
757 bwe_loss_based_updates.push_back(rtc_event);
758 break;
759 }
760 case RtcEvent::Type::DtlsTransportState: {
761 auto* rtc_event =
762 static_cast<const RtcEventDtlsTransportState* const>(it->get());
763 dtls_transport_states.push_back(rtc_event);
764 break;
765 }
766 case RtcEvent::Type::DtlsWritableState: {
767 auto* rtc_event =
768 static_cast<const RtcEventDtlsWritableState* const>(it->get());
769 dtls_writable_states.push_back(rtc_event);
770 break;
771 }
772 case RtcEvent::Type::ProbeClusterCreated: {
773 auto* rtc_event =
774 static_cast<const RtcEventProbeClusterCreated* const>(it->get());
775 probe_cluster_created_events.push_back(rtc_event);
776 break;
777 }
778 case RtcEvent::Type::ProbeResultFailure: {
779 auto* rtc_event =
780 static_cast<const RtcEventProbeResultFailure* const>(it->get());
781 probe_result_failure_events.push_back(rtc_event);
782 break;
783 }
784 case RtcEvent::Type::ProbeResultSuccess: {
785 auto* rtc_event =
786 static_cast<const RtcEventProbeResultSuccess* const>(it->get());
787 probe_result_success_events.push_back(rtc_event);
788 break;
789 }
790 case RtcEvent::Type::RouteChangeEvent: {
791 auto* rtc_event =
792 static_cast<const RtcEventRouteChange* const>(it->get());
793 route_change_events.push_back(rtc_event);
794 break;
795 }
796 case RtcEvent::Type::RemoteEstimateEvent: {
797 auto* rtc_event =
798 static_cast<const RtcEventRemoteEstimate* const>(it->get());
799 remote_estimate_events.push_back(rtc_event);
800 break;
801 }
802 case RtcEvent::Type::RtcpPacketIncoming: {
803 auto* rtc_event =
804 static_cast<const RtcEventRtcpPacketIncoming* const>(it->get());
805 incoming_rtcp_packets.push_back(rtc_event);
806 break;
807 }
808 case RtcEvent::Type::RtcpPacketOutgoing: {
809 auto* rtc_event =
810 static_cast<const RtcEventRtcpPacketOutgoing* const>(it->get());
811 outgoing_rtcp_packets.push_back(rtc_event);
812 break;
813 }
814 case RtcEvent::Type::RtpPacketIncoming: {
815 auto* rtc_event =
816 static_cast<const RtcEventRtpPacketIncoming* const>(it->get());
817 auto& v = incoming_rtp_packets[rtc_event->Ssrc()];
818 v.emplace_back(rtc_event);
819 break;
820 }
821 case RtcEvent::Type::RtpPacketOutgoing: {
822 auto* rtc_event =
823 static_cast<const RtcEventRtpPacketOutgoing* const>(it->get());
824 auto& v = outgoing_rtp_packets[rtc_event->Ssrc()];
825 v.emplace_back(rtc_event);
826 break;
827 }
828 case RtcEvent::Type::VideoReceiveStreamConfig: {
829 auto* rtc_event =
830 static_cast<const RtcEventVideoReceiveStreamConfig* const>(
831 it->get());
832 video_recv_stream_configs.push_back(rtc_event);
833 break;
834 }
835 case RtcEvent::Type::VideoSendStreamConfig: {
836 auto* rtc_event =
837 static_cast<const RtcEventVideoSendStreamConfig* const>(
838 it->get());
839 video_send_stream_configs.push_back(rtc_event);
840 break;
841 }
842 case RtcEvent::Type::IceCandidatePairConfig: {
843 auto* rtc_event =
844 static_cast<const RtcEventIceCandidatePairConfig* const>(
845 it->get());
846 ice_candidate_configs.push_back(rtc_event);
847 break;
848 }
849 case RtcEvent::Type::IceCandidatePairEvent: {
850 auto* rtc_event =
851 static_cast<const RtcEventIceCandidatePair* const>(it->get());
852 ice_candidate_events.push_back(rtc_event);
853 break;
854 }
855 case RtcEvent::Type::GenericPacketReceived: {
856 auto* rtc_event =
857 static_cast<const RtcEventGenericPacketReceived* const>(
858 it->get());
859 generic_packets_received.push_back(rtc_event);
860 break;
861 }
862 case RtcEvent::Type::GenericPacketSent: {
863 auto* rtc_event =
864 static_cast<const RtcEventGenericPacketSent* const>(it->get());
865 generic_packets_sent.push_back(rtc_event);
866 break;
867 }
868 case RtcEvent::Type::GenericAckReceived: {
869 auto* rtc_event =
870 static_cast<const RtcEventGenericAckReceived* const>(it->get());
871 generic_acks_received.push_back(rtc_event);
872 break;
873 }
874 case RtcEvent::Type::FrameDecoded: {
875 auto* rtc_event =
876 static_cast<const RtcEventFrameDecoded* const>(it->get());
877 frames_decoded[rtc_event->ssrc()].emplace_back(rtc_event);
878 break;
879 }
880 case RtcEvent::Type::BeginV3Log:
881 case RtcEvent::Type::EndV3Log:
882 // These special events are written as part of starting
883 // and stopping the log, and only as part of version 3 of the format.
884 RTC_DCHECK_NOTREACHED();
885 break;
886 }
887 }
888
889 EncodeAlrState(alr_state_events, &event_stream);
890 EncodeAudioNetworkAdaptation(audio_network_adaptation_events,
891 &event_stream);
892 EncodeAudioPlayout(audio_playout_events, &event_stream);
893 EncodeAudioRecvStreamConfig(audio_recv_stream_configs, &event_stream);
894 EncodeAudioSendStreamConfig(audio_send_stream_configs, &event_stream);
895 EncodeBweUpdateDelayBased(bwe_delay_based_updates, &event_stream);
896 EncodeBweUpdateLossBased(bwe_loss_based_updates, &event_stream);
897 EncodeDtlsTransportState(dtls_transport_states, &event_stream);
898 EncodeDtlsWritableState(dtls_writable_states, &event_stream);
899 for (const auto& kv : frames_decoded) {
900 EncodeFramesDecoded(kv.second, &event_stream);
901 }
902 EncodeGenericAcksReceived(generic_acks_received, &event_stream);
903 EncodeGenericPacketsReceived(generic_packets_received, &event_stream);
904 EncodeGenericPacketsSent(generic_packets_sent, &event_stream);
905 EncodeIceCandidatePairConfig(ice_candidate_configs, &event_stream);
906 EncodeIceCandidatePairEvent(ice_candidate_events, &event_stream);
907 EncodeProbeClusterCreated(probe_cluster_created_events, &event_stream);
908 EncodeProbeResultFailure(probe_result_failure_events, &event_stream);
909 EncodeProbeResultSuccess(probe_result_success_events, &event_stream);
910 EncodeRouteChange(route_change_events, &event_stream);
911 EncodeRemoteEstimate(remote_estimate_events, &event_stream);
912 EncodeRtcpPacketIncoming(incoming_rtcp_packets, &event_stream);
913 EncodeRtcpPacketOutgoing(outgoing_rtcp_packets, &event_stream);
914 EncodeRtpPacketIncoming(incoming_rtp_packets, &event_stream);
915 EncodeRtpPacketOutgoing(outgoing_rtp_packets, &event_stream);
916 EncodeVideoRecvStreamConfig(video_recv_stream_configs, &event_stream);
917 EncodeVideoSendStreamConfig(video_send_stream_configs, &event_stream);
918 } // Deallocate the temporary vectors.
919
920 return event_stream.SerializeAsString();
921 }
922
EncodeAlrState(rtc::ArrayView<const RtcEventAlrState * > batch,rtclog2::EventStream * event_stream)923 void RtcEventLogEncoderNewFormat::EncodeAlrState(
924 rtc::ArrayView<const RtcEventAlrState*> batch,
925 rtclog2::EventStream* event_stream) {
926 for (const RtcEventAlrState* base_event : batch) {
927 rtclog2::AlrState* proto_batch = event_stream->add_alr_states();
928 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
929 proto_batch->set_in_alr(base_event->in_alr());
930 }
931 // TODO(terelius): Should we delta-compress this event type?
932 }
933
EncodeAudioNetworkAdaptation(rtc::ArrayView<const RtcEventAudioNetworkAdaptation * > batch,rtclog2::EventStream * event_stream)934 void RtcEventLogEncoderNewFormat::EncodeAudioNetworkAdaptation(
935 rtc::ArrayView<const RtcEventAudioNetworkAdaptation*> batch,
936 rtclog2::EventStream* event_stream) {
937 if (batch.empty())
938 return;
939
940 // Base event
941 const RtcEventAudioNetworkAdaptation* const base_event = batch[0];
942 rtclog2::AudioNetworkAdaptations* proto_batch =
943 event_stream->add_audio_network_adaptations();
944 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
945 if (base_event->config().bitrate_bps.has_value())
946 proto_batch->set_bitrate_bps(base_event->config().bitrate_bps.value());
947 if (base_event->config().frame_length_ms.has_value()) {
948 proto_batch->set_frame_length_ms(
949 base_event->config().frame_length_ms.value());
950 }
951 absl::optional<uint64_t> base_uplink_packet_loss_fraction;
952 if (base_event->config().uplink_packet_loss_fraction.has_value()) {
953 base_uplink_packet_loss_fraction = ConvertPacketLossFractionToProtoFormat(
954 base_event->config().uplink_packet_loss_fraction.value());
955 proto_batch->set_uplink_packet_loss_fraction(
956 base_uplink_packet_loss_fraction.value());
957 }
958 if (base_event->config().enable_fec.has_value())
959 proto_batch->set_enable_fec(base_event->config().enable_fec.value());
960 if (base_event->config().enable_dtx.has_value())
961 proto_batch->set_enable_dtx(base_event->config().enable_dtx.value());
962 // Note that `num_channels_deltas` encodes N as N-1, to keep deltas smaller,
963 // but there's no reason to do the same for the base event's value, since
964 // no bits will be spared.
965 if (base_event->config().num_channels.has_value())
966 proto_batch->set_num_channels(base_event->config().num_channels.value());
967
968 if (batch.size() == 1)
969 return;
970
971 // Delta encoding
972 proto_batch->set_number_of_deltas(batch.size() - 1);
973 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
974 std::string encoded_deltas;
975
976 // timestamp_ms
977 for (size_t i = 0; i < values.size(); ++i) {
978 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
979 values[i] = ToUnsigned(event->timestamp_ms());
980 }
981 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
982 if (!encoded_deltas.empty()) {
983 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
984 }
985
986 // bitrate_bps
987 for (size_t i = 0; i < values.size(); ++i) {
988 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
989 if (event->config().bitrate_bps.has_value()) {
990 values[i] = ToUnsigned(event->config().bitrate_bps.value());
991 } else {
992 values[i].reset();
993 }
994 }
995 const absl::optional<uint64_t> unsigned_base_bitrate_bps =
996 base_event->config().bitrate_bps.has_value()
997 ? ToUnsigned(base_event->config().bitrate_bps.value())
998 : absl::optional<uint64_t>();
999 encoded_deltas = EncodeDeltas(unsigned_base_bitrate_bps, values);
1000 if (!encoded_deltas.empty()) {
1001 proto_batch->set_bitrate_bps_deltas(encoded_deltas);
1002 }
1003
1004 // frame_length_ms
1005 for (size_t i = 0; i < values.size(); ++i) {
1006 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
1007 if (event->config().frame_length_ms.has_value()) {
1008 values[i] = ToUnsigned(event->config().frame_length_ms.value());
1009 } else {
1010 values[i].reset();
1011 }
1012 }
1013 const absl::optional<uint64_t> unsigned_base_frame_length_ms =
1014 base_event->config().frame_length_ms.has_value()
1015 ? ToUnsigned(base_event->config().frame_length_ms.value())
1016 : absl::optional<uint64_t>();
1017 encoded_deltas = EncodeDeltas(unsigned_base_frame_length_ms, values);
1018 if (!encoded_deltas.empty()) {
1019 proto_batch->set_frame_length_ms_deltas(encoded_deltas);
1020 }
1021
1022 // uplink_packet_loss_fraction
1023 for (size_t i = 0; i < values.size(); ++i) {
1024 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
1025 if (event->config().uplink_packet_loss_fraction.has_value()) {
1026 values[i] = ConvertPacketLossFractionToProtoFormat(
1027 event->config().uplink_packet_loss_fraction.value());
1028 } else {
1029 values[i].reset();
1030 }
1031 }
1032 encoded_deltas = EncodeDeltas(base_uplink_packet_loss_fraction, values);
1033 if (!encoded_deltas.empty()) {
1034 proto_batch->set_uplink_packet_loss_fraction_deltas(encoded_deltas);
1035 }
1036
1037 // enable_fec
1038 for (size_t i = 0; i < values.size(); ++i) {
1039 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
1040 values[i] = event->config().enable_fec;
1041 }
1042 encoded_deltas = EncodeDeltas(base_event->config().enable_fec, values);
1043 if (!encoded_deltas.empty()) {
1044 proto_batch->set_enable_fec_deltas(encoded_deltas);
1045 }
1046
1047 // enable_dtx
1048 for (size_t i = 0; i < values.size(); ++i) {
1049 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
1050 values[i] = event->config().enable_dtx;
1051 }
1052 encoded_deltas = EncodeDeltas(base_event->config().enable_dtx, values);
1053 if (!encoded_deltas.empty()) {
1054 proto_batch->set_enable_dtx_deltas(encoded_deltas);
1055 }
1056
1057 // num_channels
1058 for (size_t i = 0; i < values.size(); ++i) {
1059 const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
1060 const absl::optional<size_t> num_channels = event->config().num_channels;
1061 if (num_channels.has_value()) {
1062 // Since the number of channels is always greater than 0, we can encode
1063 // N channels as N-1, thereby making sure that we get smaller deltas.
1064 // That is, a toggle of 1->2->1 can be encoded as deltas vector (1, 1),
1065 // rather than as (1, 3) or (1, -1), either of which would require two
1066 // bits per delta.
1067 RTC_DCHECK_GT(num_channels.value(), 0u);
1068 values[i] = num_channels.value() - 1;
1069 } else {
1070 values[i].reset();
1071 }
1072 }
1073 // In the base event, N channels encoded as N channels, but for delta
1074 // compression purposes, also shifted down by 1.
1075 absl::optional<size_t> shifted_base_num_channels;
1076 if (base_event->config().num_channels.has_value()) {
1077 RTC_DCHECK_GT(base_event->config().num_channels.value(), 0u);
1078 shifted_base_num_channels = base_event->config().num_channels.value() - 1;
1079 }
1080 encoded_deltas = EncodeDeltas(shifted_base_num_channels, values);
1081 if (!encoded_deltas.empty()) {
1082 proto_batch->set_num_channels_deltas(encoded_deltas);
1083 }
1084 }
1085
EncodeAudioPlayout(rtc::ArrayView<const RtcEventAudioPlayout * > batch,rtclog2::EventStream * event_stream)1086 void RtcEventLogEncoderNewFormat::EncodeAudioPlayout(
1087 rtc::ArrayView<const RtcEventAudioPlayout*> batch,
1088 rtclog2::EventStream* event_stream) {
1089 if (batch.empty())
1090 return;
1091
1092 // Base event
1093 const RtcEventAudioPlayout* const base_event = batch[0];
1094 rtclog2::AudioPlayoutEvents* proto_batch =
1095 event_stream->add_audio_playout_events();
1096 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1097 proto_batch->set_local_ssrc(base_event->ssrc());
1098
1099 if (batch.size() == 1)
1100 return;
1101
1102 // Delta encoding
1103 proto_batch->set_number_of_deltas(batch.size() - 1);
1104 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1105 std::string encoded_deltas;
1106
1107 // timestamp_ms
1108 for (size_t i = 0; i < values.size(); ++i) {
1109 const RtcEventAudioPlayout* event = batch[i + 1];
1110 values[i] = ToUnsigned(event->timestamp_ms());
1111 }
1112 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1113 if (!encoded_deltas.empty()) {
1114 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1115 }
1116
1117 // local_ssrc
1118 for (size_t i = 0; i < values.size(); ++i) {
1119 const RtcEventAudioPlayout* event = batch[i + 1];
1120 values[i] = event->ssrc();
1121 }
1122 encoded_deltas = EncodeDeltas(base_event->ssrc(), values);
1123 if (!encoded_deltas.empty()) {
1124 proto_batch->set_local_ssrc_deltas(encoded_deltas);
1125 }
1126 }
1127
EncodeAudioRecvStreamConfig(rtc::ArrayView<const RtcEventAudioReceiveStreamConfig * > batch,rtclog2::EventStream * event_stream)1128 void RtcEventLogEncoderNewFormat::EncodeAudioRecvStreamConfig(
1129 rtc::ArrayView<const RtcEventAudioReceiveStreamConfig*> batch,
1130 rtclog2::EventStream* event_stream) {
1131 for (const RtcEventAudioReceiveStreamConfig* base_event : batch) {
1132 rtclog2::AudioRecvStreamConfig* proto_batch =
1133 event_stream->add_audio_recv_stream_configs();
1134 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1135 proto_batch->set_remote_ssrc(base_event->config().remote_ssrc);
1136 proto_batch->set_local_ssrc(base_event->config().local_ssrc);
1137
1138 rtclog2::RtpHeaderExtensionConfig* proto_config =
1139 proto_batch->mutable_header_extensions();
1140 bool has_recognized_extensions =
1141 ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
1142 if (!has_recognized_extensions)
1143 proto_batch->clear_header_extensions();
1144 }
1145 }
1146
EncodeAudioSendStreamConfig(rtc::ArrayView<const RtcEventAudioSendStreamConfig * > batch,rtclog2::EventStream * event_stream)1147 void RtcEventLogEncoderNewFormat::EncodeAudioSendStreamConfig(
1148 rtc::ArrayView<const RtcEventAudioSendStreamConfig*> batch,
1149 rtclog2::EventStream* event_stream) {
1150 for (const RtcEventAudioSendStreamConfig* base_event : batch) {
1151 rtclog2::AudioSendStreamConfig* proto_batch =
1152 event_stream->add_audio_send_stream_configs();
1153 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1154 proto_batch->set_ssrc(base_event->config().local_ssrc);
1155
1156 rtclog2::RtpHeaderExtensionConfig* proto_config =
1157 proto_batch->mutable_header_extensions();
1158 bool has_recognized_extensions =
1159 ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
1160 if (!has_recognized_extensions)
1161 proto_batch->clear_header_extensions();
1162 }
1163 }
1164
EncodeBweUpdateDelayBased(rtc::ArrayView<const RtcEventBweUpdateDelayBased * > batch,rtclog2::EventStream * event_stream)1165 void RtcEventLogEncoderNewFormat::EncodeBweUpdateDelayBased(
1166 rtc::ArrayView<const RtcEventBweUpdateDelayBased*> batch,
1167 rtclog2::EventStream* event_stream) {
1168 if (batch.empty())
1169 return;
1170
1171 // Base event
1172 const RtcEventBweUpdateDelayBased* const base_event = batch[0];
1173 rtclog2::DelayBasedBweUpdates* proto_batch =
1174 event_stream->add_delay_based_bwe_updates();
1175 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1176 proto_batch->set_bitrate_bps(base_event->bitrate_bps());
1177 proto_batch->set_detector_state(
1178 ConvertToProtoFormat(base_event->detector_state()));
1179
1180 if (batch.size() == 1)
1181 return;
1182
1183 // Delta encoding
1184 proto_batch->set_number_of_deltas(batch.size() - 1);
1185 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1186 std::string encoded_deltas;
1187
1188 // timestamp_ms
1189 for (size_t i = 0; i < values.size(); ++i) {
1190 const RtcEventBweUpdateDelayBased* event = batch[i + 1];
1191 values[i] = ToUnsigned(event->timestamp_ms());
1192 }
1193 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1194 if (!encoded_deltas.empty()) {
1195 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1196 }
1197
1198 // bitrate_bps
1199 for (size_t i = 0; i < values.size(); ++i) {
1200 const RtcEventBweUpdateDelayBased* event = batch[i + 1];
1201 values[i] = event->bitrate_bps();
1202 }
1203 encoded_deltas = EncodeDeltas(base_event->bitrate_bps(), values);
1204 if (!encoded_deltas.empty()) {
1205 proto_batch->set_bitrate_bps_deltas(encoded_deltas);
1206 }
1207
1208 // detector_state
1209 for (size_t i = 0; i < values.size(); ++i) {
1210 const RtcEventBweUpdateDelayBased* event = batch[i + 1];
1211 values[i] =
1212 static_cast<uint64_t>(ConvertToProtoFormat(event->detector_state()));
1213 }
1214 encoded_deltas = EncodeDeltas(
1215 static_cast<uint64_t>(ConvertToProtoFormat(base_event->detector_state())),
1216 values);
1217 if (!encoded_deltas.empty()) {
1218 proto_batch->set_detector_state_deltas(encoded_deltas);
1219 }
1220 }
1221
EncodeBweUpdateLossBased(rtc::ArrayView<const RtcEventBweUpdateLossBased * > batch,rtclog2::EventStream * event_stream)1222 void RtcEventLogEncoderNewFormat::EncodeBweUpdateLossBased(
1223 rtc::ArrayView<const RtcEventBweUpdateLossBased*> batch,
1224 rtclog2::EventStream* event_stream) {
1225 if (batch.empty())
1226 return;
1227
1228 // Base event
1229 const RtcEventBweUpdateLossBased* const base_event = batch[0];
1230 rtclog2::LossBasedBweUpdates* proto_batch =
1231 event_stream->add_loss_based_bwe_updates();
1232 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1233 proto_batch->set_bitrate_bps(base_event->bitrate_bps());
1234 proto_batch->set_fraction_loss(base_event->fraction_loss());
1235 proto_batch->set_total_packets(base_event->total_packets());
1236
1237 if (batch.size() == 1)
1238 return;
1239
1240 // Delta encoding
1241 proto_batch->set_number_of_deltas(batch.size() - 1);
1242 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1243 std::string encoded_deltas;
1244
1245 // timestamp_ms
1246 for (size_t i = 0; i < values.size(); ++i) {
1247 const RtcEventBweUpdateLossBased* event = batch[i + 1];
1248 values[i] = ToUnsigned(event->timestamp_ms());
1249 }
1250 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1251 if (!encoded_deltas.empty()) {
1252 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1253 }
1254
1255 // bitrate_bps
1256 for (size_t i = 0; i < values.size(); ++i) {
1257 const RtcEventBweUpdateLossBased* event = batch[i + 1];
1258 values[i] = event->bitrate_bps();
1259 }
1260 encoded_deltas = EncodeDeltas(base_event->bitrate_bps(), values);
1261 if (!encoded_deltas.empty()) {
1262 proto_batch->set_bitrate_bps_deltas(encoded_deltas);
1263 }
1264
1265 // fraction_loss
1266 for (size_t i = 0; i < values.size(); ++i) {
1267 const RtcEventBweUpdateLossBased* event = batch[i + 1];
1268 values[i] = event->fraction_loss();
1269 }
1270 encoded_deltas = EncodeDeltas(base_event->fraction_loss(), values);
1271 if (!encoded_deltas.empty()) {
1272 proto_batch->set_fraction_loss_deltas(encoded_deltas);
1273 }
1274
1275 // total_packets
1276 for (size_t i = 0; i < values.size(); ++i) {
1277 const RtcEventBweUpdateLossBased* event = batch[i + 1];
1278 values[i] = event->total_packets();
1279 }
1280 encoded_deltas = EncodeDeltas(base_event->total_packets(), values);
1281 if (!encoded_deltas.empty()) {
1282 proto_batch->set_total_packets_deltas(encoded_deltas);
1283 }
1284 }
1285
EncodeDtlsTransportState(rtc::ArrayView<const RtcEventDtlsTransportState * > batch,rtclog2::EventStream * event_stream)1286 void RtcEventLogEncoderNewFormat::EncodeDtlsTransportState(
1287 rtc::ArrayView<const RtcEventDtlsTransportState*> batch,
1288 rtclog2::EventStream* event_stream) {
1289 for (const RtcEventDtlsTransportState* base_event : batch) {
1290 rtclog2::DtlsTransportStateEvent* proto_batch =
1291 event_stream->add_dtls_transport_state_events();
1292 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1293 proto_batch->set_dtls_transport_state(
1294 ConvertToProtoFormat(base_event->dtls_transport_state()));
1295 }
1296 }
1297
EncodeDtlsWritableState(rtc::ArrayView<const RtcEventDtlsWritableState * > batch,rtclog2::EventStream * event_stream)1298 void RtcEventLogEncoderNewFormat::EncodeDtlsWritableState(
1299 rtc::ArrayView<const RtcEventDtlsWritableState*> batch,
1300 rtclog2::EventStream* event_stream) {
1301 for (const RtcEventDtlsWritableState* base_event : batch) {
1302 rtclog2::DtlsWritableState* proto_batch =
1303 event_stream->add_dtls_writable_states();
1304 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1305 proto_batch->set_writable(base_event->writable());
1306 }
1307 }
1308
EncodeProbeClusterCreated(rtc::ArrayView<const RtcEventProbeClusterCreated * > batch,rtclog2::EventStream * event_stream)1309 void RtcEventLogEncoderNewFormat::EncodeProbeClusterCreated(
1310 rtc::ArrayView<const RtcEventProbeClusterCreated*> batch,
1311 rtclog2::EventStream* event_stream) {
1312 for (const RtcEventProbeClusterCreated* base_event : batch) {
1313 rtclog2::BweProbeCluster* proto_batch = event_stream->add_probe_clusters();
1314 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1315 proto_batch->set_id(base_event->id());
1316 proto_batch->set_bitrate_bps(base_event->bitrate_bps());
1317 proto_batch->set_min_packets(base_event->min_probes());
1318 proto_batch->set_min_bytes(base_event->min_bytes());
1319 }
1320 }
1321
EncodeProbeResultFailure(rtc::ArrayView<const RtcEventProbeResultFailure * > batch,rtclog2::EventStream * event_stream)1322 void RtcEventLogEncoderNewFormat::EncodeProbeResultFailure(
1323 rtc::ArrayView<const RtcEventProbeResultFailure*> batch,
1324 rtclog2::EventStream* event_stream) {
1325 for (const RtcEventProbeResultFailure* base_event : batch) {
1326 rtclog2::BweProbeResultFailure* proto_batch =
1327 event_stream->add_probe_failure();
1328 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1329 proto_batch->set_id(base_event->id());
1330 proto_batch->set_failure(
1331 ConvertToProtoFormat(base_event->failure_reason()));
1332 }
1333 // TODO(terelius): Should we delta-compress this event type?
1334 }
1335
EncodeProbeResultSuccess(rtc::ArrayView<const RtcEventProbeResultSuccess * > batch,rtclog2::EventStream * event_stream)1336 void RtcEventLogEncoderNewFormat::EncodeProbeResultSuccess(
1337 rtc::ArrayView<const RtcEventProbeResultSuccess*> batch,
1338 rtclog2::EventStream* event_stream) {
1339 for (const RtcEventProbeResultSuccess* base_event : batch) {
1340 rtclog2::BweProbeResultSuccess* proto_batch =
1341 event_stream->add_probe_success();
1342 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1343 proto_batch->set_id(base_event->id());
1344 proto_batch->set_bitrate_bps(base_event->bitrate_bps());
1345 }
1346 // TODO(terelius): Should we delta-compress this event type?
1347 }
1348
EncodeRouteChange(rtc::ArrayView<const RtcEventRouteChange * > batch,rtclog2::EventStream * event_stream)1349 void RtcEventLogEncoderNewFormat::EncodeRouteChange(
1350 rtc::ArrayView<const RtcEventRouteChange*> batch,
1351 rtclog2::EventStream* event_stream) {
1352 for (const RtcEventRouteChange* base_event : batch) {
1353 rtclog2::RouteChange* proto_batch = event_stream->add_route_changes();
1354 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1355 proto_batch->set_connected(base_event->connected());
1356 proto_batch->set_overhead(base_event->overhead());
1357 }
1358 // TODO(terelius): Should we delta-compress this event type?
1359 }
1360
EncodeRemoteEstimate(rtc::ArrayView<const RtcEventRemoteEstimate * > batch,rtclog2::EventStream * event_stream)1361 void RtcEventLogEncoderNewFormat::EncodeRemoteEstimate(
1362 rtc::ArrayView<const RtcEventRemoteEstimate*> batch,
1363 rtclog2::EventStream* event_stream) {
1364 if (batch.empty())
1365 return;
1366
1367 // Base event
1368 const auto* const base_event = batch[0];
1369 rtclog2::RemoteEstimates* proto_batch = event_stream->add_remote_estimates();
1370
1371 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1372
1373 absl::optional<uint64_t> base_link_capacity_lower;
1374 if (base_event->link_capacity_lower_.IsFinite()) {
1375 base_link_capacity_lower =
1376 base_event->link_capacity_lower_.kbps<uint32_t>();
1377 proto_batch->set_link_capacity_lower_kbps(*base_link_capacity_lower);
1378 }
1379 absl::optional<uint64_t> base_link_capacity_upper;
1380 if (base_event->link_capacity_upper_.IsFinite()) {
1381 base_link_capacity_upper =
1382 base_event->link_capacity_upper_.kbps<uint32_t>();
1383 proto_batch->set_link_capacity_upper_kbps(*base_link_capacity_upper);
1384 }
1385
1386 if (batch.size() == 1)
1387 return;
1388
1389 // Delta encoding
1390 proto_batch->set_number_of_deltas(batch.size() - 1);
1391 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1392 std::string encoded_deltas;
1393
1394 // timestamp_ms
1395 for (size_t i = 0; i < values.size(); ++i) {
1396 const auto* event = batch[i + 1];
1397 values[i] = ToUnsigned(event->timestamp_ms());
1398 }
1399 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1400 if (!encoded_deltas.empty()) {
1401 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1402 }
1403
1404 // link_capacity_lower_kbps
1405 for (size_t i = 0; i < values.size(); ++i) {
1406 const auto* event = batch[i + 1];
1407 if (event->link_capacity_lower_.IsFinite()) {
1408 values[i] = event->link_capacity_lower_.kbps<uint32_t>();
1409 } else {
1410 values[i].reset();
1411 }
1412 }
1413 encoded_deltas = EncodeDeltas(base_link_capacity_lower, values);
1414 if (!encoded_deltas.empty()) {
1415 proto_batch->set_link_capacity_lower_kbps_deltas(encoded_deltas);
1416 }
1417
1418 // link_capacity_upper_kbps
1419 for (size_t i = 0; i < values.size(); ++i) {
1420 const auto* event = batch[i + 1];
1421 if (event->link_capacity_upper_.IsFinite()) {
1422 values[i] = event->link_capacity_upper_.kbps<uint32_t>();
1423 } else {
1424 values[i].reset();
1425 }
1426 }
1427 encoded_deltas = EncodeDeltas(base_link_capacity_upper, values);
1428 if (!encoded_deltas.empty()) {
1429 proto_batch->set_link_capacity_upper_kbps_deltas(encoded_deltas);
1430 }
1431 }
1432
EncodeRtcpPacketIncoming(rtc::ArrayView<const RtcEventRtcpPacketIncoming * > batch,rtclog2::EventStream * event_stream)1433 void RtcEventLogEncoderNewFormat::EncodeRtcpPacketIncoming(
1434 rtc::ArrayView<const RtcEventRtcpPacketIncoming*> batch,
1435 rtclog2::EventStream* event_stream) {
1436 if (batch.empty()) {
1437 return;
1438 }
1439 EncodeRtcpPacket(batch, event_stream->add_incoming_rtcp_packets());
1440 }
1441
EncodeRtcpPacketOutgoing(rtc::ArrayView<const RtcEventRtcpPacketOutgoing * > batch,rtclog2::EventStream * event_stream)1442 void RtcEventLogEncoderNewFormat::EncodeRtcpPacketOutgoing(
1443 rtc::ArrayView<const RtcEventRtcpPacketOutgoing*> batch,
1444 rtclog2::EventStream* event_stream) {
1445 if (batch.empty()) {
1446 return;
1447 }
1448 EncodeRtcpPacket(batch, event_stream->add_outgoing_rtcp_packets());
1449 }
1450
EncodeRtpPacketIncoming(const std::map<uint32_t,std::vector<const RtcEventRtpPacketIncoming * >> & batch,rtclog2::EventStream * event_stream)1451 void RtcEventLogEncoderNewFormat::EncodeRtpPacketIncoming(
1452 const std::map<uint32_t, std::vector<const RtcEventRtpPacketIncoming*>>&
1453 batch,
1454 rtclog2::EventStream* event_stream) {
1455 for (const auto& it : batch) {
1456 RTC_DCHECK(!it.second.empty());
1457 EncodeRtpPacket(it.second, event_stream->add_incoming_rtp_packets());
1458 }
1459 }
1460
EncodeFramesDecoded(rtc::ArrayView<const RtcEventFrameDecoded * const> batch,rtclog2::EventStream * event_stream)1461 void RtcEventLogEncoderNewFormat::EncodeFramesDecoded(
1462 rtc::ArrayView<const RtcEventFrameDecoded* const> batch,
1463 rtclog2::EventStream* event_stream) {
1464 if (batch.empty()) {
1465 return;
1466 }
1467 const RtcEventFrameDecoded* const base_event = batch[0];
1468 rtclog2::FrameDecodedEvents* proto_batch =
1469 event_stream->add_frame_decoded_events();
1470 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1471 proto_batch->set_ssrc(base_event->ssrc());
1472 proto_batch->set_render_time_ms(base_event->render_time_ms());
1473 proto_batch->set_width(base_event->width());
1474 proto_batch->set_height(base_event->height());
1475 proto_batch->set_codec(ConvertToProtoFormat(base_event->codec()));
1476 proto_batch->set_qp(base_event->qp());
1477
1478 if (batch.size() == 1) {
1479 return;
1480 }
1481
1482 // Delta encoding
1483 proto_batch->set_number_of_deltas(batch.size() - 1);
1484 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1485 std::string encoded_deltas;
1486
1487 // timestamp_ms
1488 for (size_t i = 0; i < values.size(); ++i) {
1489 const RtcEventFrameDecoded* event = batch[i + 1];
1490 values[i] = ToUnsigned(event->timestamp_ms());
1491 }
1492 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1493 if (!encoded_deltas.empty()) {
1494 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1495 }
1496
1497 // SSRC
1498 for (size_t i = 0; i < values.size(); ++i) {
1499 const RtcEventFrameDecoded* event = batch[i + 1];
1500 values[i] = event->ssrc();
1501 }
1502 encoded_deltas = EncodeDeltas(base_event->ssrc(), values);
1503 if (!encoded_deltas.empty()) {
1504 proto_batch->set_ssrc_deltas(encoded_deltas);
1505 }
1506
1507 // render_time_ms
1508 for (size_t i = 0; i < values.size(); ++i) {
1509 const RtcEventFrameDecoded* event = batch[i + 1];
1510 values[i] = ToUnsigned(event->render_time_ms());
1511 }
1512 encoded_deltas =
1513 EncodeDeltas(ToUnsigned(base_event->render_time_ms()), values);
1514 if (!encoded_deltas.empty()) {
1515 proto_batch->set_render_time_ms_deltas(encoded_deltas);
1516 }
1517
1518 // width
1519 for (size_t i = 0; i < values.size(); ++i) {
1520 const RtcEventFrameDecoded* event = batch[i + 1];
1521 values[i] = ToUnsigned(event->width());
1522 }
1523 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->width()), values);
1524 if (!encoded_deltas.empty()) {
1525 proto_batch->set_width_deltas(encoded_deltas);
1526 }
1527
1528 // height
1529 for (size_t i = 0; i < values.size(); ++i) {
1530 const RtcEventFrameDecoded* event = batch[i + 1];
1531 values[i] = ToUnsigned(event->height());
1532 }
1533 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->height()), values);
1534 if (!encoded_deltas.empty()) {
1535 proto_batch->set_height_deltas(encoded_deltas);
1536 }
1537
1538 // codec
1539 for (size_t i = 0; i < values.size(); ++i) {
1540 const RtcEventFrameDecoded* event = batch[i + 1];
1541 values[i] = static_cast<uint64_t>(ConvertToProtoFormat(event->codec()));
1542 }
1543 encoded_deltas = EncodeDeltas(
1544 static_cast<uint64_t>(ConvertToProtoFormat(base_event->codec())), values);
1545 if (!encoded_deltas.empty()) {
1546 proto_batch->set_codec_deltas(encoded_deltas);
1547 }
1548
1549 // qp
1550 for (size_t i = 0; i < values.size(); ++i) {
1551 const RtcEventFrameDecoded* event = batch[i + 1];
1552 values[i] = event->qp();
1553 }
1554 encoded_deltas = EncodeDeltas(base_event->qp(), values);
1555 if (!encoded_deltas.empty()) {
1556 proto_batch->set_qp_deltas(encoded_deltas);
1557 }
1558 }
1559
EncodeGenericPacketsSent(rtc::ArrayView<const RtcEventGenericPacketSent * > batch,rtclog2::EventStream * event_stream)1560 void RtcEventLogEncoderNewFormat::EncodeGenericPacketsSent(
1561 rtc::ArrayView<const RtcEventGenericPacketSent*> batch,
1562 rtclog2::EventStream* event_stream) {
1563 if (batch.empty()) {
1564 return;
1565 }
1566 const RtcEventGenericPacketSent* const base_event = batch[0];
1567 rtclog2::GenericPacketSent* proto_batch =
1568 event_stream->add_generic_packets_sent();
1569 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1570 proto_batch->set_packet_number(base_event->packet_number());
1571 proto_batch->set_overhead_length(base_event->overhead_length());
1572 proto_batch->set_payload_length(base_event->payload_length());
1573 proto_batch->set_padding_length(base_event->padding_length());
1574
1575 // Delta encoding
1576 proto_batch->set_number_of_deltas(batch.size() - 1);
1577 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1578 std::string encoded_deltas;
1579
1580 if (batch.size() == 1) {
1581 return;
1582 }
1583
1584 // timestamp_ms
1585 for (size_t i = 0; i < values.size(); ++i) {
1586 const RtcEventGenericPacketSent* event = batch[i + 1];
1587 values[i] = ToUnsigned(event->timestamp_ms());
1588 }
1589 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1590 if (!encoded_deltas.empty()) {
1591 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1592 }
1593
1594 // packet_number
1595 for (size_t i = 0; i < values.size(); ++i) {
1596 const RtcEventGenericPacketSent* event = batch[i + 1];
1597 values[i] = ToUnsigned(event->packet_number());
1598 }
1599 encoded_deltas =
1600 EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
1601 if (!encoded_deltas.empty()) {
1602 proto_batch->set_packet_number_deltas(encoded_deltas);
1603 }
1604
1605 // overhead_length
1606 for (size_t i = 0; i < values.size(); ++i) {
1607 const RtcEventGenericPacketSent* event = batch[i + 1];
1608 values[i] = event->overhead_length();
1609 }
1610 encoded_deltas = EncodeDeltas(base_event->overhead_length(), values);
1611 if (!encoded_deltas.empty()) {
1612 proto_batch->set_overhead_length_deltas(encoded_deltas);
1613 }
1614
1615 // payload_length
1616 for (size_t i = 0; i < values.size(); ++i) {
1617 const RtcEventGenericPacketSent* event = batch[i + 1];
1618 values[i] = event->payload_length();
1619 }
1620 encoded_deltas = EncodeDeltas(base_event->payload_length(), values);
1621 if (!encoded_deltas.empty()) {
1622 proto_batch->set_payload_length_deltas(encoded_deltas);
1623 }
1624
1625 // padding_length
1626 for (size_t i = 0; i < values.size(); ++i) {
1627 const RtcEventGenericPacketSent* event = batch[i + 1];
1628 values[i] = event->padding_length();
1629 }
1630 encoded_deltas = EncodeDeltas(base_event->padding_length(), values);
1631 if (!encoded_deltas.empty()) {
1632 proto_batch->set_padding_length_deltas(encoded_deltas);
1633 }
1634 }
1635
EncodeGenericPacketsReceived(rtc::ArrayView<const RtcEventGenericPacketReceived * > batch,rtclog2::EventStream * event_stream)1636 void RtcEventLogEncoderNewFormat::EncodeGenericPacketsReceived(
1637 rtc::ArrayView<const RtcEventGenericPacketReceived*> batch,
1638 rtclog2::EventStream* event_stream) {
1639 if (batch.empty()) {
1640 return;
1641 }
1642 const RtcEventGenericPacketReceived* const base_event = batch[0];
1643 rtclog2::GenericPacketReceived* proto_batch =
1644 event_stream->add_generic_packets_received();
1645 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1646 proto_batch->set_packet_number(base_event->packet_number());
1647 proto_batch->set_packet_length(base_event->packet_length());
1648
1649 // Delta encoding
1650 proto_batch->set_number_of_deltas(batch.size() - 1);
1651 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1652 std::string encoded_deltas;
1653
1654 if (batch.size() == 1) {
1655 return;
1656 }
1657
1658 // timestamp_ms
1659 for (size_t i = 0; i < values.size(); ++i) {
1660 const RtcEventGenericPacketReceived* event = batch[i + 1];
1661 values[i] = ToUnsigned(event->timestamp_ms());
1662 }
1663 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1664 if (!encoded_deltas.empty()) {
1665 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1666 }
1667
1668 // packet_number
1669 for (size_t i = 0; i < values.size(); ++i) {
1670 const RtcEventGenericPacketReceived* event = batch[i + 1];
1671 values[i] = ToUnsigned(event->packet_number());
1672 }
1673 encoded_deltas =
1674 EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
1675 if (!encoded_deltas.empty()) {
1676 proto_batch->set_packet_number_deltas(encoded_deltas);
1677 }
1678
1679 // packet_length
1680 for (size_t i = 0; i < values.size(); ++i) {
1681 const RtcEventGenericPacketReceived* event = batch[i + 1];
1682 values[i] = event->packet_length();
1683 }
1684 encoded_deltas = EncodeDeltas(base_event->packet_length(), values);
1685 if (!encoded_deltas.empty()) {
1686 proto_batch->set_packet_length_deltas(encoded_deltas);
1687 }
1688 }
1689
EncodeGenericAcksReceived(rtc::ArrayView<const RtcEventGenericAckReceived * > batch,rtclog2::EventStream * event_stream)1690 void RtcEventLogEncoderNewFormat::EncodeGenericAcksReceived(
1691 rtc::ArrayView<const RtcEventGenericAckReceived*> batch,
1692 rtclog2::EventStream* event_stream) {
1693 if (batch.empty()) {
1694 return;
1695 }
1696 const RtcEventGenericAckReceived* const base_event = batch[0];
1697 rtclog2::GenericAckReceived* proto_batch =
1698 event_stream->add_generic_acks_received();
1699 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1700 proto_batch->set_packet_number(base_event->packet_number());
1701 proto_batch->set_acked_packet_number(base_event->acked_packet_number());
1702 absl::optional<uint64_t> base_receive_timestamp;
1703 if (base_event->receive_acked_packet_time_ms()) {
1704 int64_t receive_acked_packet_time_ms =
1705 base_event->receive_acked_packet_time_ms().value();
1706 base_receive_timestamp = ToUnsigned(receive_acked_packet_time_ms);
1707 proto_batch->set_receive_acked_packet_time_ms(receive_acked_packet_time_ms);
1708 }
1709
1710 // Delta encoding
1711 proto_batch->set_number_of_deltas(batch.size() - 1);
1712 std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
1713 std::string encoded_deltas;
1714
1715 if (batch.size() == 1) {
1716 return;
1717 }
1718
1719 // timestamp_ms
1720 for (size_t i = 0; i < values.size(); ++i) {
1721 const RtcEventGenericAckReceived* event = batch[i + 1];
1722 values[i] = ToUnsigned(event->timestamp_ms());
1723 }
1724 encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
1725 if (!encoded_deltas.empty()) {
1726 proto_batch->set_timestamp_ms_deltas(encoded_deltas);
1727 }
1728
1729 // packet_number
1730 for (size_t i = 0; i < values.size(); ++i) {
1731 const RtcEventGenericAckReceived* event = batch[i + 1];
1732 values[i] = ToUnsigned(event->packet_number());
1733 }
1734 encoded_deltas =
1735 EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
1736 if (!encoded_deltas.empty()) {
1737 proto_batch->set_packet_number_deltas(encoded_deltas);
1738 }
1739
1740 // acked packet number
1741 for (size_t i = 0; i < values.size(); ++i) {
1742 const RtcEventGenericAckReceived* event = batch[i + 1];
1743 values[i] = ToUnsigned(event->acked_packet_number());
1744 }
1745 encoded_deltas =
1746 EncodeDeltas(ToUnsigned(base_event->acked_packet_number()), values);
1747 if (!encoded_deltas.empty()) {
1748 proto_batch->set_acked_packet_number_deltas(encoded_deltas);
1749 }
1750
1751 // receive timestamp
1752 for (size_t i = 0; i < values.size(); ++i) {
1753 const RtcEventGenericAckReceived* event = batch[i + 1];
1754 if (event->receive_acked_packet_time_ms()) {
1755 values[i] = ToUnsigned(event->receive_acked_packet_time_ms().value());
1756 } else {
1757 values[i] = absl::nullopt;
1758 }
1759 }
1760 encoded_deltas = EncodeDeltas(base_receive_timestamp, values);
1761 if (!encoded_deltas.empty()) {
1762 proto_batch->set_receive_acked_packet_time_ms_deltas(encoded_deltas);
1763 }
1764 }
1765
EncodeRtpPacketOutgoing(const std::map<uint32_t,std::vector<const RtcEventRtpPacketOutgoing * >> & batch,rtclog2::EventStream * event_stream)1766 void RtcEventLogEncoderNewFormat::EncodeRtpPacketOutgoing(
1767 const std::map<uint32_t, std::vector<const RtcEventRtpPacketOutgoing*>>&
1768 batch,
1769 rtclog2::EventStream* event_stream) {
1770 for (const auto& it : batch) {
1771 RTC_DCHECK(!it.second.empty());
1772 EncodeRtpPacket(it.second, event_stream->add_outgoing_rtp_packets());
1773 }
1774 }
1775
EncodeVideoRecvStreamConfig(rtc::ArrayView<const RtcEventVideoReceiveStreamConfig * > batch,rtclog2::EventStream * event_stream)1776 void RtcEventLogEncoderNewFormat::EncodeVideoRecvStreamConfig(
1777 rtc::ArrayView<const RtcEventVideoReceiveStreamConfig*> batch,
1778 rtclog2::EventStream* event_stream) {
1779 for (const RtcEventVideoReceiveStreamConfig* base_event : batch) {
1780 rtclog2::VideoRecvStreamConfig* proto_batch =
1781 event_stream->add_video_recv_stream_configs();
1782 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1783 proto_batch->set_remote_ssrc(base_event->config().remote_ssrc);
1784 proto_batch->set_local_ssrc(base_event->config().local_ssrc);
1785 proto_batch->set_rtx_ssrc(base_event->config().rtx_ssrc);
1786
1787 rtclog2::RtpHeaderExtensionConfig* proto_config =
1788 proto_batch->mutable_header_extensions();
1789 bool has_recognized_extensions =
1790 ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
1791 if (!has_recognized_extensions)
1792 proto_batch->clear_header_extensions();
1793 }
1794 }
1795
EncodeVideoSendStreamConfig(rtc::ArrayView<const RtcEventVideoSendStreamConfig * > batch,rtclog2::EventStream * event_stream)1796 void RtcEventLogEncoderNewFormat::EncodeVideoSendStreamConfig(
1797 rtc::ArrayView<const RtcEventVideoSendStreamConfig*> batch,
1798 rtclog2::EventStream* event_stream) {
1799 for (const RtcEventVideoSendStreamConfig* base_event : batch) {
1800 rtclog2::VideoSendStreamConfig* proto_batch =
1801 event_stream->add_video_send_stream_configs();
1802 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1803 proto_batch->set_ssrc(base_event->config().local_ssrc);
1804 proto_batch->set_rtx_ssrc(base_event->config().rtx_ssrc);
1805
1806 rtclog2::RtpHeaderExtensionConfig* proto_config =
1807 proto_batch->mutable_header_extensions();
1808 bool has_recognized_extensions =
1809 ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
1810 if (!has_recognized_extensions)
1811 proto_batch->clear_header_extensions();
1812 }
1813 }
1814
EncodeIceCandidatePairConfig(rtc::ArrayView<const RtcEventIceCandidatePairConfig * > batch,rtclog2::EventStream * event_stream)1815 void RtcEventLogEncoderNewFormat::EncodeIceCandidatePairConfig(
1816 rtc::ArrayView<const RtcEventIceCandidatePairConfig*> batch,
1817 rtclog2::EventStream* event_stream) {
1818 for (const RtcEventIceCandidatePairConfig* base_event : batch) {
1819 rtclog2::IceCandidatePairConfig* proto_batch =
1820 event_stream->add_ice_candidate_configs();
1821
1822 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1823 proto_batch->set_config_type(ConvertToProtoFormat(base_event->type()));
1824 proto_batch->set_candidate_pair_id(base_event->candidate_pair_id());
1825 const auto& desc = base_event->candidate_pair_desc();
1826 proto_batch->set_local_candidate_type(
1827 ConvertToProtoFormat(desc.local_candidate_type));
1828 proto_batch->set_local_relay_protocol(
1829 ConvertToProtoFormat(desc.local_relay_protocol));
1830 proto_batch->set_local_network_type(
1831 ConvertToProtoFormat(desc.local_network_type));
1832 proto_batch->set_local_address_family(
1833 ConvertToProtoFormat(desc.local_address_family));
1834 proto_batch->set_remote_candidate_type(
1835 ConvertToProtoFormat(desc.remote_candidate_type));
1836 proto_batch->set_remote_address_family(
1837 ConvertToProtoFormat(desc.remote_address_family));
1838 proto_batch->set_candidate_pair_protocol(
1839 ConvertToProtoFormat(desc.candidate_pair_protocol));
1840 }
1841 // TODO(terelius): Should we delta-compress this event type?
1842 }
1843
EncodeIceCandidatePairEvent(rtc::ArrayView<const RtcEventIceCandidatePair * > batch,rtclog2::EventStream * event_stream)1844 void RtcEventLogEncoderNewFormat::EncodeIceCandidatePairEvent(
1845 rtc::ArrayView<const RtcEventIceCandidatePair*> batch,
1846 rtclog2::EventStream* event_stream) {
1847 for (const RtcEventIceCandidatePair* base_event : batch) {
1848 rtclog2::IceCandidatePairEvent* proto_batch =
1849 event_stream->add_ice_candidate_events();
1850
1851 proto_batch->set_timestamp_ms(base_event->timestamp_ms());
1852
1853 proto_batch->set_event_type(ConvertToProtoFormat(base_event->type()));
1854 proto_batch->set_candidate_pair_id(base_event->candidate_pair_id());
1855 proto_batch->set_transaction_id(base_event->transaction_id());
1856 }
1857 // TODO(terelius): Should we delta-compress this event type?
1858 }
1859
1860 } // namespace webrtc
1861