/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
#include "logging/rtc_event_log/encoder/delta_encoding.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
#include "logging/rtc_event_log/events/rtc_event_route_change.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "rtc_base/checks.h"
#include "rtc_base/ignore_wundef.h"
#include "rtc_base/logging.h"

// *.pb.h files are generated at build-time by the protobuf compiler.
RTC_PUSH_IGNORING_WUNDEF()
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log2.pb.h"
#else
#include "logging/rtc_event_log/rtc_event_log2.pb.h"
#endif
RTC_POP_IGNORING_WUNDEF()

using webrtc_event_logging::ToUnsigned;

namespace webrtc {

namespace {
rtclog2::DelayBasedBweUpdates::DetectorState ConvertToProtoFormat(
    BandwidthUsage state) {
  switch (state) {
    case BandwidthUsage::kBwNormal:
      return rtclog2::DelayBasedBweUpdates::BWE_NORMAL;
    case BandwidthUsage::kBwUnderusing:
      return rtclog2::DelayBasedBweUpdates::BWE_UNDERUSING;
    case BandwidthUsage::kBwOverusing:
      return rtclog2::DelayBasedBweUpdates::BWE_OVERUSING;
    case BandwidthUsage::kLast:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE;
}

rtclog2::BweProbeResultFailure::FailureReason ConvertToProtoFormat(
    ProbeFailureReason failure_reason) {
  switch (failure_reason) {
    case ProbeFailureReason::kInvalidSendReceiveInterval:
      return rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_INTERVAL;
    case ProbeFailureReason::kInvalidSendReceiveRatio:
      return rtclog2::BweProbeResultFailure::INVALID_SEND_RECEIVE_RATIO;
    case ProbeFailureReason::kTimeout:
      return rtclog2::BweProbeResultFailure::TIMEOUT;
    case ProbeFailureReason::kLast:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::BweProbeResultFailure::UNKNOWN;
}

// Returns true if there are recognized extensions that we should log
// and false if there are no extensions or all extensions are types we don't
// log. The protobuf representation of the header configs is written to
// |proto_config|.
bool ConvertToProtoFormat(const std::vector<RtpExtension>& extensions,
                          rtclog2::RtpHeaderExtensionConfig* proto_config) {
  size_t unknown_extensions = 0;
  for (auto& extension : extensions) {
    if (extension.uri == RtpExtension::kAudioLevelUri) {
      proto_config->set_audio_level_id(extension.id);
    } else if (extension.uri == RtpExtension::kTimestampOffsetUri) {
      proto_config->set_transmission_time_offset_id(extension.id);
    } else if (extension.uri == RtpExtension::kAbsSendTimeUri) {
      proto_config->set_absolute_send_time_id(extension.id);
    } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
      proto_config->set_transport_sequence_number_id(extension.id);
    } else if (extension.uri == RtpExtension::kVideoRotationUri) {
      proto_config->set_video_rotation_id(extension.id);
    } else {
      ++unknown_extensions;
    }
  }
  return unknown_extensions < extensions.size();
}

rtclog2::DtlsTransportStateEvent::DtlsTransportState ConvertToProtoFormat(
    webrtc::DtlsTransportState state) {
  switch (state) {
    case webrtc::DtlsTransportState::kNew:
      return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_NEW;
    case webrtc::DtlsTransportState::kConnecting:
      return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTING;
    case webrtc::DtlsTransportState::kConnected:
      return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CONNECTED;
    case webrtc::DtlsTransportState::kClosed:
      return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_CLOSED;
    case webrtc::DtlsTransportState::kFailed:
      return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_FAILED;
    case webrtc::DtlsTransportState::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::DtlsTransportStateEvent::UNKNOWN_DTLS_TRANSPORT_STATE;
}

rtclog2::IceCandidatePairConfig::IceCandidatePairConfigType
ConvertToProtoFormat(IceCandidatePairConfigType type) {
  switch (type) {
    case IceCandidatePairConfigType::kAdded:
      return rtclog2::IceCandidatePairConfig::ADDED;
    case IceCandidatePairConfigType::kUpdated:
      return rtclog2::IceCandidatePairConfig::UPDATED;
    case IceCandidatePairConfigType::kDestroyed:
      return rtclog2::IceCandidatePairConfig::DESTROYED;
    case IceCandidatePairConfigType::kSelected:
      return rtclog2::IceCandidatePairConfig::SELECTED;
    case IceCandidatePairConfigType::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairConfig::UNKNOWN_CONFIG_TYPE;
}

rtclog2::IceCandidatePairConfig::IceCandidateType ConvertToProtoFormat(
    IceCandidateType type) {
  switch (type) {
    case IceCandidateType::kUnknown:
      return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
    case IceCandidateType::kLocal:
      return rtclog2::IceCandidatePairConfig::LOCAL;
    case IceCandidateType::kStun:
      return rtclog2::IceCandidatePairConfig::STUN;
    case IceCandidateType::kPrflx:
      return rtclog2::IceCandidatePairConfig::PRFLX;
    case IceCandidateType::kRelay:
      return rtclog2::IceCandidatePairConfig::RELAY;
    case IceCandidateType::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
}

rtclog2::IceCandidatePairConfig::Protocol ConvertToProtoFormat(
    IceCandidatePairProtocol protocol) {
  switch (protocol) {
    case IceCandidatePairProtocol::kUnknown:
      return rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
    case IceCandidatePairProtocol::kUdp:
      return rtclog2::IceCandidatePairConfig::UDP;
    case IceCandidatePairProtocol::kTcp:
      return rtclog2::IceCandidatePairConfig::TCP;
    case IceCandidatePairProtocol::kSsltcp:
      return rtclog2::IceCandidatePairConfig::SSLTCP;
    case IceCandidatePairProtocol::kTls:
      return rtclog2::IceCandidatePairConfig::TLS;
    case IceCandidatePairProtocol::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
}

rtclog2::IceCandidatePairConfig::AddressFamily ConvertToProtoFormat(
    IceCandidatePairAddressFamily address_family) {
  switch (address_family) {
    case IceCandidatePairAddressFamily::kUnknown:
      return rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
    case IceCandidatePairAddressFamily::kIpv4:
      return rtclog2::IceCandidatePairConfig::IPV4;
    case IceCandidatePairAddressFamily::kIpv6:
      return rtclog2::IceCandidatePairConfig::IPV6;
    case IceCandidatePairAddressFamily::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
}

rtclog2::IceCandidatePairConfig::NetworkType ConvertToProtoFormat(
    IceCandidateNetworkType network_type) {
  switch (network_type) {
    case IceCandidateNetworkType::kUnknown:
      return rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
    case IceCandidateNetworkType::kEthernet:
      return rtclog2::IceCandidatePairConfig::ETHERNET;
    case IceCandidateNetworkType::kLoopback:
      return rtclog2::IceCandidatePairConfig::LOOPBACK;
    case IceCandidateNetworkType::kWifi:
      return rtclog2::IceCandidatePairConfig::WIFI;
    case IceCandidateNetworkType::kVpn:
      return rtclog2::IceCandidatePairConfig::VPN;
    case IceCandidateNetworkType::kCellular:
      return rtclog2::IceCandidatePairConfig::CELLULAR;
    case IceCandidateNetworkType::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
}

rtclog2::IceCandidatePairEvent::IceCandidatePairEventType ConvertToProtoFormat(
    IceCandidatePairEventType type) {
  switch (type) {
    case IceCandidatePairEventType::kCheckSent:
      return rtclog2::IceCandidatePairEvent::CHECK_SENT;
    case IceCandidatePairEventType::kCheckReceived:
      return rtclog2::IceCandidatePairEvent::CHECK_RECEIVED;
    case IceCandidatePairEventType::kCheckResponseSent:
      return rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_SENT;
    case IceCandidatePairEventType::kCheckResponseReceived:
      return rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED;
    case IceCandidatePairEventType::kNumValues:
      RTC_NOTREACHED();
  }
  RTC_NOTREACHED();
  return rtclog2::IceCandidatePairEvent::UNKNOWN_CHECK_TYPE;
}

// Copies all RTCP blocks except APP, SDES and unknown from |packet| to
// |buffer|. |buffer| must have space for |IP_PACKET_SIZE| bytes. |packet| must
// be at most |IP_PACKET_SIZE| bytes long.
size_t RemoveNonWhitelistedRtcpBlocks(const rtc::Buffer& packet,
                                      uint8_t* buffer) {
  RTC_DCHECK(packet.size() <= IP_PACKET_SIZE);
  RTC_DCHECK(buffer != nullptr);
  rtcp::CommonHeader header;
  const uint8_t* block_begin = packet.data();
  const uint8_t* packet_end = packet.data() + packet.size();
  size_t buffer_length = 0;
  while (block_begin < packet_end) {
    if (!header.Parse(block_begin, packet_end - block_begin)) {
      break;  // Incorrect message header.
    }
    const uint8_t* next_block = header.NextPacket();
    RTC_DCHECK_GT(next_block, block_begin);
    RTC_DCHECK_LE(next_block, packet_end);
    size_t block_size = next_block - block_begin;
    switch (header.type()) {
      case rtcp::Bye::kPacketType:
      case rtcp::ExtendedJitterReport::kPacketType:
      case rtcp::ExtendedReports::kPacketType:
      case rtcp::Psfb::kPacketType:
      case rtcp::ReceiverReport::kPacketType:
      case rtcp::Rtpfb::kPacketType:
      case rtcp::SenderReport::kPacketType:
        // We log sender reports, receiver reports, bye messages
        // inter-arrival jitter, third-party loss reports, payload-specific
        // feedback and extended reports.
        // TODO(terelius): As an optimization, don't copy anything if all blocks
        // in the packet are whitelisted types.
        memcpy(buffer + buffer_length, block_begin, block_size);
        buffer_length += block_size;
        break;
      case rtcp::App::kPacketType:
      case rtcp::Sdes::kPacketType:
      default:
        // We don't log sender descriptions, application defined messages
        // or message blocks of unknown type.
        break;
    }

    block_begin += block_size;
  }
  return buffer_length;
}

template <typename EventType, typename ProtoType>
void EncodeRtcpPacket(rtc::ArrayView<const EventType*> batch,
                      ProtoType* proto_batch) {
  if (batch.empty()) {
    return;
  }

  // Base event
  const EventType* const base_event = batch[0];
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  {
    uint8_t buffer[IP_PACKET_SIZE];
    size_t buffer_length =
        RemoveNonWhitelistedRtcpBlocks(base_event->packet(), buffer);
    proto_batch->set_raw_packet(buffer, buffer_length);
  }

  if (batch.size() == 1) {
    return;
  }

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // raw_packet
  std::vector<std::string> scrubed_packets(batch.size() - 1);
  for (size_t i = 0; i < scrubed_packets.size(); ++i) {
    const EventType* event = batch[i + 1];
    scrubed_packets[i].resize(event->packet().size());
    static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "");
    const size_t buffer_length = RemoveNonWhitelistedRtcpBlocks(
        event->packet(), reinterpret_cast<uint8_t*>(&scrubed_packets[i][0]));
    if (buffer_length < event->packet().size()) {
      scrubed_packets[i].resize(buffer_length);
    }
  }
  proto_batch->set_raw_packet_blobs(EncodeBlobs(scrubed_packets));
}

template <typename EventType, typename ProtoType>
void EncodeRtpPacket(const std::vector<const EventType*>& batch,
                     ProtoType* proto_batch) {
  if (batch.empty()) {
    return;
  }

  // Base event
  const EventType* const base_event = batch[0];
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_marker(base_event->header().Marker());
  // TODO(terelius): Is payload type needed?
  proto_batch->set_payload_type(base_event->header().PayloadType());
  proto_batch->set_sequence_number(base_event->header().SequenceNumber());
  proto_batch->set_rtp_timestamp(base_event->header().Timestamp());
  proto_batch->set_ssrc(base_event->header().Ssrc());
  proto_batch->set_payload_size(base_event->payload_length());
  proto_batch->set_header_size(base_event->header_length());
  proto_batch->set_padding_size(base_event->padding_length());

  // Add header extensions (base event).
  absl::optional<uint64_t> base_transport_sequence_number;
  {
    uint16_t seqnum;
    if (base_event->header().template GetExtension<TransportSequenceNumber>(
            &seqnum)) {
      proto_batch->set_transport_sequence_number(seqnum);
      base_transport_sequence_number = seqnum;
    }
  }

  absl::optional<uint64_t> unsigned_base_transmission_time_offset;
  {
    int32_t offset;
    if (base_event->header().template GetExtension<TransmissionOffset>(
            &offset)) {
      proto_batch->set_transmission_time_offset(offset);
      unsigned_base_transmission_time_offset = ToUnsigned(offset);
    }
  }

  absl::optional<uint64_t> base_absolute_send_time;
  {
    uint32_t sendtime;
    if (base_event->header().template GetExtension<AbsoluteSendTime>(
            &sendtime)) {
      proto_batch->set_absolute_send_time(sendtime);
      base_absolute_send_time = sendtime;
    }
  }

  absl::optional<uint64_t> base_video_rotation;
  {
    VideoRotation video_rotation;
    if (base_event->header().template GetExtension<VideoOrientation>(
            &video_rotation)) {
      proto_batch->set_video_rotation(
          ConvertVideoRotationToCVOByte(video_rotation));
      base_video_rotation = ConvertVideoRotationToCVOByte(video_rotation);
    }
  }

  absl::optional<uint64_t> base_audio_level;
  absl::optional<uint64_t> base_voice_activity;
  {
    bool voice_activity;
    uint8_t audio_level;
    if (base_event->header().template GetExtension<AudioLevel>(&voice_activity,
                                                               &audio_level)) {
      RTC_DCHECK_LE(audio_level, 0x7Fu);
      base_audio_level = audio_level;
      proto_batch->set_audio_level(audio_level);

      base_voice_activity = voice_activity;
      proto_batch->set_voice_activity(voice_activity);
    }
  }

  if (batch.size() == 1) {
    return;
  }

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms (event)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // marker (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header().Marker();
  }
  encoded_deltas = EncodeDeltas(base_event->header().Marker(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_marker_deltas(encoded_deltas);
  }

  // payload_type (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header().PayloadType();
  }
  encoded_deltas = EncodeDeltas(base_event->header().PayloadType(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_payload_type_deltas(encoded_deltas);
  }

  // sequence_number (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header().SequenceNumber();
  }
  encoded_deltas = EncodeDeltas(base_event->header().SequenceNumber(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_sequence_number_deltas(encoded_deltas);
  }

  // rtp_timestamp (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header().Timestamp();
  }
  encoded_deltas = EncodeDeltas(base_event->header().Timestamp(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_rtp_timestamp_deltas(encoded_deltas);
  }

  // ssrc (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header().Ssrc();
  }
  encoded_deltas = EncodeDeltas(base_event->header().Ssrc(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_ssrc_deltas(encoded_deltas);
  }

  // payload_size (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->payload_length();
  }
  encoded_deltas = EncodeDeltas(base_event->payload_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_payload_size_deltas(encoded_deltas);
  }

  // header_size (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->header_length();
  }
  encoded_deltas = EncodeDeltas(base_event->header_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_header_size_deltas(encoded_deltas);
  }

  // padding_size (RTP base)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    values[i] = event->padding_length();
  }
  encoded_deltas = EncodeDeltas(base_event->padding_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_padding_size_deltas(encoded_deltas);
  }

  // transport_sequence_number (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    uint16_t seqnum;
    if (event->header().template GetExtension<TransportSequenceNumber>(
            &seqnum)) {
      values[i] = seqnum;
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_transport_sequence_number, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_transport_sequence_number_deltas(encoded_deltas);
  }

  // transmission_time_offset (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    int32_t offset;
    if (event->header().template GetExtension<TransmissionOffset>(&offset)) {
      values[i] = ToUnsigned(offset);
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(unsigned_base_transmission_time_offset, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_transmission_time_offset_deltas(encoded_deltas);
  }

  // absolute_send_time (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    uint32_t sendtime;
    if (event->header().template GetExtension<AbsoluteSendTime>(&sendtime)) {
      values[i] = sendtime;
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_absolute_send_time, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_absolute_send_time_deltas(encoded_deltas);
  }

  // video_rotation (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    VideoRotation video_rotation;
    if (event->header().template GetExtension<VideoOrientation>(
            &video_rotation)) {
      values[i] = ConvertVideoRotationToCVOByte(video_rotation);
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_video_rotation, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_video_rotation_deltas(encoded_deltas);
  }

  // audio_level (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    bool voice_activity;
    uint8_t audio_level;
    if (event->header().template GetExtension<AudioLevel>(&voice_activity,
                                                          &audio_level)) {
      RTC_DCHECK_LE(audio_level, 0x7Fu);
      values[i] = audio_level;
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_audio_level, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_audio_level_deltas(encoded_deltas);
  }

  // voice_activity (RTP extension)
  for (size_t i = 0; i < values.size(); ++i) {
    const EventType* event = batch[i + 1];
    bool voice_activity;
    uint8_t audio_level;
    if (event->header().template GetExtension<AudioLevel>(&voice_activity,
                                                          &audio_level)) {
      RTC_DCHECK_LE(audio_level, 0x7Fu);
      values[i] = voice_activity;
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_voice_activity, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_voice_activity_deltas(encoded_deltas);
  }
}
}  // namespace

std::string RtcEventLogEncoderNewFormat::EncodeLogStart(int64_t timestamp_us,
                                                        int64_t utc_time_us) {
  rtclog2::EventStream event_stream;
  rtclog2::BeginLogEvent* proto_batch = event_stream.add_begin_log_events();
  proto_batch->set_timestamp_ms(timestamp_us / 1000);
  proto_batch->set_version(2);
  proto_batch->set_utc_time_ms(utc_time_us / 1000);
  return event_stream.SerializeAsString();
}

std::string RtcEventLogEncoderNewFormat::EncodeLogEnd(int64_t timestamp_us) {
  rtclog2::EventStream event_stream;
  rtclog2::EndLogEvent* proto_batch = event_stream.add_end_log_events();
  proto_batch->set_timestamp_ms(timestamp_us / 1000);
  return event_stream.SerializeAsString();
}

std::string RtcEventLogEncoderNewFormat::EncodeBatch(
    std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
    std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) {
  rtclog2::EventStream event_stream;
  std::string encoded_output;

  {
    std::vector<const RtcEventAlrState*> alr_state_events;
    std::vector<const RtcEventAudioNetworkAdaptation*>
        audio_network_adaptation_events;
    std::vector<const RtcEventAudioPlayout*> audio_playout_events;
    std::vector<const RtcEventAudioReceiveStreamConfig*>
        audio_recv_stream_configs;
    std::vector<const RtcEventAudioSendStreamConfig*> audio_send_stream_configs;
    std::vector<const RtcEventBweUpdateDelayBased*> bwe_delay_based_updates;
    std::vector<const RtcEventBweUpdateLossBased*> bwe_loss_based_updates;
    std::vector<const RtcEventDtlsTransportState*> dtls_transport_states;
    std::vector<const RtcEventDtlsWritableState*> dtls_writable_states;
    std::vector<const RtcEventGenericAckReceived*> generic_acks_received;
    std::vector<const RtcEventGenericPacketReceived*> generic_packets_received;
    std::vector<const RtcEventGenericPacketSent*> generic_packets_sent;
    std::vector<const RtcEventIceCandidatePair*> ice_candidate_events;
    std::vector<const RtcEventIceCandidatePairConfig*> ice_candidate_configs;
    std::vector<const RtcEventProbeClusterCreated*>
        probe_cluster_created_events;
    std::vector<const RtcEventProbeResultFailure*> probe_result_failure_events;
    std::vector<const RtcEventProbeResultSuccess*> probe_result_success_events;
    std::vector<const RtcEventRouteChange*> route_change_events;
    std::vector<const RtcEventRemoteEstimate*> remote_estimate_events;
    std::vector<const RtcEventRtcpPacketIncoming*> incoming_rtcp_packets;
    std::vector<const RtcEventRtcpPacketOutgoing*> outgoing_rtcp_packets;
    std::map<uint32_t /* SSRC */, std::vector<const RtcEventRtpPacketIncoming*>>
        incoming_rtp_packets;
    std::map<uint32_t /* SSRC */, std::vector<const RtcEventRtpPacketOutgoing*>>
        outgoing_rtp_packets;
    std::vector<const RtcEventVideoReceiveStreamConfig*>
        video_recv_stream_configs;
    std::vector<const RtcEventVideoSendStreamConfig*> video_send_stream_configs;

    for (auto it = begin; it != end; ++it) {
      switch ((*it)->GetType()) {
        case RtcEvent::Type::AlrStateEvent: {
          auto* rtc_event =
              static_cast<const RtcEventAlrState* const>(it->get());
          alr_state_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::AudioNetworkAdaptation: {
          auto* rtc_event =
              static_cast<const RtcEventAudioNetworkAdaptation* const>(
                  it->get());
          audio_network_adaptation_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::AudioPlayout: {
          auto* rtc_event =
              static_cast<const RtcEventAudioPlayout* const>(it->get());
          audio_playout_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::AudioReceiveStreamConfig: {
          auto* rtc_event =
              static_cast<const RtcEventAudioReceiveStreamConfig* const>(
                  it->get());
          audio_recv_stream_configs.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::AudioSendStreamConfig: {
          auto* rtc_event =
              static_cast<const RtcEventAudioSendStreamConfig* const>(
                  it->get());
          audio_send_stream_configs.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::BweUpdateDelayBased: {
          auto* rtc_event =
              static_cast<const RtcEventBweUpdateDelayBased* const>(it->get());
          bwe_delay_based_updates.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::BweUpdateLossBased: {
          auto* rtc_event =
              static_cast<const RtcEventBweUpdateLossBased* const>(it->get());
          bwe_loss_based_updates.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::DtlsTransportState: {
          auto* rtc_event =
              static_cast<const RtcEventDtlsTransportState* const>(it->get());
          dtls_transport_states.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::DtlsWritableState: {
          auto* rtc_event =
              static_cast<const RtcEventDtlsWritableState* const>(it->get());
          dtls_writable_states.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::ProbeClusterCreated: {
          auto* rtc_event =
              static_cast<const RtcEventProbeClusterCreated* const>(it->get());
          probe_cluster_created_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::ProbeResultFailure: {
          auto* rtc_event =
              static_cast<const RtcEventProbeResultFailure* const>(it->get());
          probe_result_failure_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::ProbeResultSuccess: {
          auto* rtc_event =
              static_cast<const RtcEventProbeResultSuccess* const>(it->get());
          probe_result_success_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RouteChangeEvent: {
          auto* rtc_event =
              static_cast<const RtcEventRouteChange* const>(it->get());
          route_change_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RemoteEstimateEvent: {
          auto* rtc_event =
              static_cast<const RtcEventRemoteEstimate* const>(it->get());
          remote_estimate_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RtcpPacketIncoming: {
          auto* rtc_event =
              static_cast<const RtcEventRtcpPacketIncoming* const>(it->get());
          incoming_rtcp_packets.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RtcpPacketOutgoing: {
          auto* rtc_event =
              static_cast<const RtcEventRtcpPacketOutgoing* const>(it->get());
          outgoing_rtcp_packets.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RtpPacketIncoming: {
          auto* rtc_event =
              static_cast<const RtcEventRtpPacketIncoming* const>(it->get());
          auto& v = incoming_rtp_packets[rtc_event->header().Ssrc()];
          v.emplace_back(rtc_event);
          break;
        }
        case RtcEvent::Type::RtpPacketOutgoing: {
          auto* rtc_event =
              static_cast<const RtcEventRtpPacketOutgoing* const>(it->get());
          auto& v = outgoing_rtp_packets[rtc_event->header().Ssrc()];
          v.emplace_back(rtc_event);
          break;
        }
        case RtcEvent::Type::VideoReceiveStreamConfig: {
          auto* rtc_event =
              static_cast<const RtcEventVideoReceiveStreamConfig* const>(
                  it->get());
          video_recv_stream_configs.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::VideoSendStreamConfig: {
          auto* rtc_event =
              static_cast<const RtcEventVideoSendStreamConfig* const>(
                  it->get());
          video_send_stream_configs.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::IceCandidatePairConfig: {
          auto* rtc_event =
              static_cast<const RtcEventIceCandidatePairConfig* const>(
                  it->get());
          ice_candidate_configs.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::IceCandidatePairEvent: {
          auto* rtc_event =
              static_cast<const RtcEventIceCandidatePair* const>(it->get());
          ice_candidate_events.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::GenericPacketReceived: {
          auto* rtc_event =
              static_cast<const RtcEventGenericPacketReceived* const>(
                  it->get());
          generic_packets_received.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::GenericPacketSent: {
          auto* rtc_event =
              static_cast<const RtcEventGenericPacketSent* const>(it->get());
          generic_packets_sent.push_back(rtc_event);
          break;
        }
        case RtcEvent::Type::GenericAckReceived: {
          auto* rtc_event =
              static_cast<const RtcEventGenericAckReceived* const>(it->get());
          generic_acks_received.push_back(rtc_event);
          break;
        }
      }
    }

    EncodeAlrState(alr_state_events, &event_stream);
    EncodeAudioNetworkAdaptation(audio_network_adaptation_events,
                                 &event_stream);
    EncodeAudioPlayout(audio_playout_events, &event_stream);
    EncodeAudioRecvStreamConfig(audio_recv_stream_configs, &event_stream);
    EncodeAudioSendStreamConfig(audio_send_stream_configs, &event_stream);
    EncodeBweUpdateDelayBased(bwe_delay_based_updates, &event_stream);
    EncodeBweUpdateLossBased(bwe_loss_based_updates, &event_stream);
    EncodeDtlsTransportState(dtls_transport_states, &event_stream);
    EncodeDtlsWritableState(dtls_writable_states, &event_stream);
    EncodeGenericAcksReceived(generic_acks_received, &event_stream);
    EncodeGenericPacketsReceived(generic_packets_received, &event_stream);
    EncodeGenericPacketsSent(generic_packets_sent, &event_stream);
    EncodeIceCandidatePairConfig(ice_candidate_configs, &event_stream);
    EncodeIceCandidatePairEvent(ice_candidate_events, &event_stream);
    EncodeProbeClusterCreated(probe_cluster_created_events, &event_stream);
    EncodeProbeResultFailure(probe_result_failure_events, &event_stream);
    EncodeProbeResultSuccess(probe_result_success_events, &event_stream);
    EncodeRouteChange(route_change_events, &event_stream);
    EncodeRemoteEstimate(remote_estimate_events, &event_stream);
    EncodeRtcpPacketIncoming(incoming_rtcp_packets, &event_stream);
    EncodeRtcpPacketOutgoing(outgoing_rtcp_packets, &event_stream);
    EncodeRtpPacketIncoming(incoming_rtp_packets, &event_stream);
    EncodeRtpPacketOutgoing(outgoing_rtp_packets, &event_stream);
    EncodeVideoRecvStreamConfig(video_recv_stream_configs, &event_stream);
    EncodeVideoSendStreamConfig(video_send_stream_configs, &event_stream);
  }  // Deallocate the temporary vectors.

  return event_stream.SerializeAsString();
}

void RtcEventLogEncoderNewFormat::EncodeAlrState(
    rtc::ArrayView<const RtcEventAlrState*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventAlrState* base_event : batch) {
    rtclog2::AlrState* proto_batch = event_stream->add_alr_states();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_in_alr(base_event->in_alr());
  }
  // TODO(terelius): Should we delta-compress this event type?
}

void RtcEventLogEncoderNewFormat::EncodeAudioNetworkAdaptation(
    rtc::ArrayView<const RtcEventAudioNetworkAdaptation*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty())
    return;

  // Base event
  const RtcEventAudioNetworkAdaptation* const base_event = batch[0];
  rtclog2::AudioNetworkAdaptations* proto_batch =
      event_stream->add_audio_network_adaptations();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  if (base_event->config().bitrate_bps.has_value())
    proto_batch->set_bitrate_bps(base_event->config().bitrate_bps.value());
  if (base_event->config().frame_length_ms.has_value()) {
    proto_batch->set_frame_length_ms(
        base_event->config().frame_length_ms.value());
  }
  absl::optional<uint64_t> base_uplink_packet_loss_fraction;
  if (base_event->config().uplink_packet_loss_fraction.has_value()) {
    base_uplink_packet_loss_fraction = ConvertPacketLossFractionToProtoFormat(
        base_event->config().uplink_packet_loss_fraction.value());
    proto_batch->set_uplink_packet_loss_fraction(
        base_uplink_packet_loss_fraction.value());
  }
  if (base_event->config().enable_fec.has_value())
    proto_batch->set_enable_fec(base_event->config().enable_fec.value());
  if (base_event->config().enable_dtx.has_value())
    proto_batch->set_enable_dtx(base_event->config().enable_dtx.value());
  // Note that |num_channels_deltas| encodes N as N-1, to keep deltas smaller,
  // but there's no reason to do the same for the base event's value, since
  // no bits will be spared.
  if (base_event->config().num_channels.has_value())
    proto_batch->set_num_channels(base_event->config().num_channels.value());

  if (batch.size() == 1)
    return;

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // bitrate_bps
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    if (event->config().bitrate_bps.has_value()) {
      values[i] = ToUnsigned(event->config().bitrate_bps.value());
    } else {
      values[i].reset();
    }
  }
  const absl::optional<uint64_t> unsigned_base_bitrate_bps =
      base_event->config().bitrate_bps.has_value()
          ? ToUnsigned(base_event->config().bitrate_bps.value())
          : absl::optional<uint64_t>();
  encoded_deltas = EncodeDeltas(unsigned_base_bitrate_bps, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_bitrate_bps_deltas(encoded_deltas);
  }

  // frame_length_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    if (event->config().frame_length_ms.has_value()) {
      values[i] = ToUnsigned(event->config().frame_length_ms.value());
    } else {
      values[i].reset();
    }
  }
  const absl::optional<uint64_t> unsigned_base_frame_length_ms =
      base_event->config().frame_length_ms.has_value()
          ? ToUnsigned(base_event->config().frame_length_ms.value())
          : absl::optional<uint64_t>();
  encoded_deltas = EncodeDeltas(unsigned_base_frame_length_ms, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_frame_length_ms_deltas(encoded_deltas);
  }

  // uplink_packet_loss_fraction
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    if (event->config().uplink_packet_loss_fraction.has_value()) {
      values[i] = ConvertPacketLossFractionToProtoFormat(
          event->config().uplink_packet_loss_fraction.value());
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_uplink_packet_loss_fraction, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_uplink_packet_loss_fraction_deltas(encoded_deltas);
  }

  // enable_fec
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    values[i] = event->config().enable_fec;
  }
  encoded_deltas = EncodeDeltas(base_event->config().enable_fec, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_enable_fec_deltas(encoded_deltas);
  }

  // enable_dtx
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    values[i] = event->config().enable_dtx;
  }
  encoded_deltas = EncodeDeltas(base_event->config().enable_dtx, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_enable_dtx_deltas(encoded_deltas);
  }

  // num_channels
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioNetworkAdaptation* event = batch[i + 1];
    const absl::optional<size_t> num_channels = event->config().num_channels;
    if (num_channels.has_value()) {
      // Since the number of channels is always greater than 0, we can encode
      // N channels as N-1, thereby making sure that we get smaller deltas.
      // That is, a toggle of 1->2->1 can be encoded as deltas vector (1, 1),
      // rather than as (1, 3) or (1, -1), either of which would require two
      // bits per delta.
      RTC_DCHECK_GT(num_channels.value(), 0u);
      values[i] = num_channels.value() - 1;
    } else {
      values[i].reset();
    }
  }
  // In the base event, N channels encoded as N channels, but for delta
  // compression purposes, also shifted down by 1.
  absl::optional<size_t> shifted_base_num_channels;
  if (base_event->config().num_channels.has_value()) {
    RTC_DCHECK_GT(base_event->config().num_channels.value(), 0u);
    shifted_base_num_channels = base_event->config().num_channels.value() - 1;
  }
  encoded_deltas = EncodeDeltas(shifted_base_num_channels, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_num_channels_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeAudioPlayout(
    rtc::ArrayView<const RtcEventAudioPlayout*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty())
    return;

  // Base event
  const RtcEventAudioPlayout* const base_event = batch[0];
  rtclog2::AudioPlayoutEvents* proto_batch =
      event_stream->add_audio_playout_events();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_local_ssrc(base_event->ssrc());

  if (batch.size() == 1)
    return;

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioPlayout* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // local_ssrc
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventAudioPlayout* event = batch[i + 1];
    values[i] = event->ssrc();
  }
  encoded_deltas = EncodeDeltas(base_event->ssrc(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_local_ssrc_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeAudioRecvStreamConfig(
    rtc::ArrayView<const RtcEventAudioReceiveStreamConfig*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventAudioReceiveStreamConfig* base_event : batch) {
    rtclog2::AudioRecvStreamConfig* proto_batch =
        event_stream->add_audio_recv_stream_configs();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_remote_ssrc(base_event->config().remote_ssrc);
    proto_batch->set_local_ssrc(base_event->config().local_ssrc);

    rtclog2::RtpHeaderExtensionConfig* proto_config =
        proto_batch->mutable_header_extensions();
    bool has_recognized_extensions =
        ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
    if (!has_recognized_extensions)
      proto_batch->clear_header_extensions();
  }
}

void RtcEventLogEncoderNewFormat::EncodeAudioSendStreamConfig(
    rtc::ArrayView<const RtcEventAudioSendStreamConfig*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventAudioSendStreamConfig* base_event : batch) {
    rtclog2::AudioSendStreamConfig* proto_batch =
        event_stream->add_audio_send_stream_configs();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_ssrc(base_event->config().local_ssrc);

    rtclog2::RtpHeaderExtensionConfig* proto_config =
        proto_batch->mutable_header_extensions();
    bool has_recognized_extensions =
        ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
    if (!has_recognized_extensions)
      proto_batch->clear_header_extensions();
  }
}

void RtcEventLogEncoderNewFormat::EncodeBweUpdateDelayBased(
    rtc::ArrayView<const RtcEventBweUpdateDelayBased*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty())
    return;

  // Base event
  const RtcEventBweUpdateDelayBased* const base_event = batch[0];
  rtclog2::DelayBasedBweUpdates* proto_batch =
      event_stream->add_delay_based_bwe_updates();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_bitrate_bps(base_event->bitrate_bps());
  proto_batch->set_detector_state(
      ConvertToProtoFormat(base_event->detector_state()));

  if (batch.size() == 1)
    return;

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateDelayBased* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // bitrate_bps
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateDelayBased* event = batch[i + 1];
    values[i] = event->bitrate_bps();
  }
  encoded_deltas = EncodeDeltas(base_event->bitrate_bps(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_bitrate_bps_deltas(encoded_deltas);
  }

  // detector_state
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateDelayBased* event = batch[i + 1];
    values[i] =
        static_cast<uint64_t>(ConvertToProtoFormat(event->detector_state()));
  }
  encoded_deltas = EncodeDeltas(
      static_cast<uint64_t>(ConvertToProtoFormat(base_event->detector_state())),
      values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_detector_state_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeBweUpdateLossBased(
    rtc::ArrayView<const RtcEventBweUpdateLossBased*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty())
    return;

  // Base event
  const RtcEventBweUpdateLossBased* const base_event = batch[0];
  rtclog2::LossBasedBweUpdates* proto_batch =
      event_stream->add_loss_based_bwe_updates();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_bitrate_bps(base_event->bitrate_bps());
  proto_batch->set_fraction_loss(base_event->fraction_loss());
  proto_batch->set_total_packets(base_event->total_packets());

  if (batch.size() == 1)
    return;

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateLossBased* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // bitrate_bps
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateLossBased* event = batch[i + 1];
    values[i] = event->bitrate_bps();
  }
  encoded_deltas = EncodeDeltas(base_event->bitrate_bps(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_bitrate_bps_deltas(encoded_deltas);
  }

  // fraction_loss
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateLossBased* event = batch[i + 1];
    values[i] = event->fraction_loss();
  }
  encoded_deltas = EncodeDeltas(base_event->fraction_loss(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_fraction_loss_deltas(encoded_deltas);
  }

  // total_packets
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventBweUpdateLossBased* event = batch[i + 1];
    values[i] = event->total_packets();
  }
  encoded_deltas = EncodeDeltas(base_event->total_packets(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_total_packets_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeDtlsTransportState(
    rtc::ArrayView<const RtcEventDtlsTransportState*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventDtlsTransportState* base_event : batch) {
    rtclog2::DtlsTransportStateEvent* proto_batch =
        event_stream->add_dtls_transport_state_events();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_dtls_transport_state(
        ConvertToProtoFormat(base_event->dtls_transport_state()));
  }
}

void RtcEventLogEncoderNewFormat::EncodeDtlsWritableState(
    rtc::ArrayView<const RtcEventDtlsWritableState*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventDtlsWritableState* base_event : batch) {
    rtclog2::DtlsWritableState* proto_batch =
        event_stream->add_dtls_writable_states();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_writable(base_event->writable());
  }
}

void RtcEventLogEncoderNewFormat::EncodeProbeClusterCreated(
    rtc::ArrayView<const RtcEventProbeClusterCreated*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventProbeClusterCreated* base_event : batch) {
    rtclog2::BweProbeCluster* proto_batch = event_stream->add_probe_clusters();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_id(base_event->id());
    proto_batch->set_bitrate_bps(base_event->bitrate_bps());
    proto_batch->set_min_packets(base_event->min_probes());
    proto_batch->set_min_bytes(base_event->min_bytes());
  }
}

void RtcEventLogEncoderNewFormat::EncodeProbeResultFailure(
    rtc::ArrayView<const RtcEventProbeResultFailure*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventProbeResultFailure* base_event : batch) {
    rtclog2::BweProbeResultFailure* proto_batch =
        event_stream->add_probe_failure();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_id(base_event->id());
    proto_batch->set_failure(
        ConvertToProtoFormat(base_event->failure_reason()));
  }
  // TODO(terelius): Should we delta-compress this event type?
}

void RtcEventLogEncoderNewFormat::EncodeProbeResultSuccess(
    rtc::ArrayView<const RtcEventProbeResultSuccess*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventProbeResultSuccess* base_event : batch) {
    rtclog2::BweProbeResultSuccess* proto_batch =
        event_stream->add_probe_success();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_id(base_event->id());
    proto_batch->set_bitrate_bps(base_event->bitrate_bps());
  }
  // TODO(terelius): Should we delta-compress this event type?
}

void RtcEventLogEncoderNewFormat::EncodeRouteChange(
    rtc::ArrayView<const RtcEventRouteChange*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventRouteChange* base_event : batch) {
    rtclog2::RouteChange* proto_batch = event_stream->add_route_changes();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_connected(base_event->connected());
    proto_batch->set_overhead(base_event->overhead());
  }
  // TODO(terelius): Should we delta-compress this event type?
}

void RtcEventLogEncoderNewFormat::EncodeRemoteEstimate(
    rtc::ArrayView<const RtcEventRemoteEstimate*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty())
    return;

  // Base event
  const auto* const base_event = batch[0];
  rtclog2::RemoteEstimates* proto_batch = event_stream->add_remote_estimates();

  proto_batch->set_timestamp_ms(base_event->timestamp_ms());

  absl::optional<uint64_t> base_link_capacity_lower;
  if (base_event->link_capacity_lower_.IsFinite()) {
    base_link_capacity_lower =
        base_event->link_capacity_lower_.kbps<uint32_t>();
    proto_batch->set_link_capacity_lower_kbps(*base_link_capacity_lower);
  }
  absl::optional<uint64_t> base_link_capacity_upper;
  if (base_event->link_capacity_upper_.IsFinite()) {
    base_link_capacity_upper =
        base_event->link_capacity_upper_.kbps<uint32_t>();
    proto_batch->set_link_capacity_upper_kbps(*base_link_capacity_upper);
  }

  if (batch.size() == 1)
    return;

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const auto* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // link_capacity_lower_kbps
  for (size_t i = 0; i < values.size(); ++i) {
    const auto* event = batch[i + 1];
    if (base_event->link_capacity_lower_.IsFinite()) {
      values[i] = event->link_capacity_lower_.kbps<uint32_t>();
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_link_capacity_lower, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_link_capacity_lower_kbps_deltas(encoded_deltas);
  }

  // link_capacity_upper_kbps
  for (size_t i = 0; i < values.size(); ++i) {
    const auto* event = batch[i + 1];
    if (base_event->link_capacity_upper_.IsFinite()) {
      values[i] = event->link_capacity_upper_.kbps<uint32_t>();
    } else {
      values[i].reset();
    }
  }
  encoded_deltas = EncodeDeltas(base_link_capacity_upper, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_link_capacity_upper_kbps_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeRtcpPacketIncoming(
    rtc::ArrayView<const RtcEventRtcpPacketIncoming*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  EncodeRtcpPacket(batch, event_stream->add_incoming_rtcp_packets());
}

void RtcEventLogEncoderNewFormat::EncodeRtcpPacketOutgoing(
    rtc::ArrayView<const RtcEventRtcpPacketOutgoing*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  EncodeRtcpPacket(batch, event_stream->add_outgoing_rtcp_packets());
}

void RtcEventLogEncoderNewFormat::EncodeRtpPacketIncoming(
    const std::map<uint32_t, std::vector<const RtcEventRtpPacketIncoming*>>&
        batch,
    rtclog2::EventStream* event_stream) {
  for (const auto& it : batch) {
    RTC_DCHECK(!it.second.empty());
    EncodeRtpPacket(it.second, event_stream->add_incoming_rtp_packets());
  }
}

void RtcEventLogEncoderNewFormat::EncodeGenericPacketsSent(
    rtc::ArrayView<const RtcEventGenericPacketSent*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  const RtcEventGenericPacketSent* const base_event = batch[0];
  rtclog2::GenericPacketSent* proto_batch =
      event_stream->add_generic_packets_sent();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_packet_number(base_event->packet_number());
  proto_batch->set_overhead_length(base_event->overhead_length());
  proto_batch->set_payload_length(base_event->payload_length());
  proto_batch->set_padding_length(base_event->padding_length());

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  if (batch.size() == 1) {
    return;
  }

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketSent* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // packet_number
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketSent* event = batch[i + 1];
    values[i] = ToUnsigned(event->packet_number());
  }
  encoded_deltas =
      EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_packet_number_deltas(encoded_deltas);
  }

  // overhead_length
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketSent* event = batch[i + 1];
    values[i] = event->overhead_length();
  }
  encoded_deltas = EncodeDeltas(base_event->overhead_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_overhead_length_deltas(encoded_deltas);
  }

  // payload_length
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketSent* event = batch[i + 1];
    values[i] = event->payload_length();
  }
  encoded_deltas = EncodeDeltas(base_event->payload_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_payload_length_deltas(encoded_deltas);
  }

  // padding_length
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketSent* event = batch[i + 1];
    values[i] = event->padding_length();
  }
  encoded_deltas = EncodeDeltas(base_event->padding_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_padding_length_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeGenericPacketsReceived(
    rtc::ArrayView<const RtcEventGenericPacketReceived*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  const RtcEventGenericPacketReceived* const base_event = batch[0];
  rtclog2::GenericPacketReceived* proto_batch =
      event_stream->add_generic_packets_received();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_packet_number(base_event->packet_number());
  proto_batch->set_packet_length(base_event->packet_length());

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  if (batch.size() == 1) {
    return;
  }

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketReceived* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // packet_number
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketReceived* event = batch[i + 1];
    values[i] = ToUnsigned(event->packet_number());
  }
  encoded_deltas =
      EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_packet_number_deltas(encoded_deltas);
  }

  // packet_length
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericPacketReceived* event = batch[i + 1];
    values[i] = event->packet_length();
  }
  encoded_deltas = EncodeDeltas(base_event->packet_length(), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_packet_length_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeGenericAcksReceived(
    rtc::ArrayView<const RtcEventGenericAckReceived*> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  const RtcEventGenericAckReceived* const base_event = batch[0];
  rtclog2::GenericAckReceived* proto_batch =
      event_stream->add_generic_acks_received();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_packet_number(base_event->packet_number());
  proto_batch->set_acked_packet_number(base_event->acked_packet_number());
  absl::optional<uint64_t> base_receive_timestamp;
  if (base_event->receive_acked_packet_time_ms()) {
    int64_t receive_acked_packet_time_ms =
        base_event->receive_acked_packet_time_ms().value();
    base_receive_timestamp = ToUnsigned(receive_acked_packet_time_ms);
    proto_batch->set_receive_acked_packet_time_ms(receive_acked_packet_time_ms);
  }

  // Delta encoding
  proto_batch->set_number_of_deltas(batch.size() - 1);
  std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
  std::string encoded_deltas;

  if (batch.size() == 1) {
    return;
  }

  // timestamp_ms
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericAckReceived* event = batch[i + 1];
    values[i] = ToUnsigned(event->timestamp_ms());
  }
  encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_timestamp_ms_deltas(encoded_deltas);
  }

  // packet_number
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericAckReceived* event = batch[i + 1];
    values[i] = ToUnsigned(event->packet_number());
  }
  encoded_deltas =
      EncodeDeltas(ToUnsigned(base_event->packet_number()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_packet_number_deltas(encoded_deltas);
  }

  // acked packet number
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericAckReceived* event = batch[i + 1];
    values[i] = ToUnsigned(event->acked_packet_number());
  }
  encoded_deltas =
      EncodeDeltas(ToUnsigned(base_event->acked_packet_number()), values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_acked_packet_number_deltas(encoded_deltas);
  }

  // receive timestamp
  for (size_t i = 0; i < values.size(); ++i) {
    const RtcEventGenericAckReceived* event = batch[i + 1];
    if (event->receive_acked_packet_time_ms()) {
      values[i] = ToUnsigned(event->receive_acked_packet_time_ms().value());
    } else {
      values[i] = absl::nullopt;
    }
  }
  encoded_deltas = EncodeDeltas(base_receive_timestamp, values);
  if (!encoded_deltas.empty()) {
    proto_batch->set_receive_acked_packet_time_ms_deltas(encoded_deltas);
  }
}

void RtcEventLogEncoderNewFormat::EncodeRtpPacketOutgoing(
    const std::map<uint32_t, std::vector<const RtcEventRtpPacketOutgoing*>>&
        batch,
    rtclog2::EventStream* event_stream) {
  for (const auto& it : batch) {
    RTC_DCHECK(!it.second.empty());
    EncodeRtpPacket(it.second, event_stream->add_outgoing_rtp_packets());
  }
}

void RtcEventLogEncoderNewFormat::EncodeVideoRecvStreamConfig(
    rtc::ArrayView<const RtcEventVideoReceiveStreamConfig*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventVideoReceiveStreamConfig* base_event : batch) {
    rtclog2::VideoRecvStreamConfig* proto_batch =
        event_stream->add_video_recv_stream_configs();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_remote_ssrc(base_event->config().remote_ssrc);
    proto_batch->set_local_ssrc(base_event->config().local_ssrc);
    proto_batch->set_rtx_ssrc(base_event->config().rtx_ssrc);

    rtclog2::RtpHeaderExtensionConfig* proto_config =
        proto_batch->mutable_header_extensions();
    bool has_recognized_extensions =
        ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
    if (!has_recognized_extensions)
      proto_batch->clear_header_extensions();
  }
}

void RtcEventLogEncoderNewFormat::EncodeVideoSendStreamConfig(
    rtc::ArrayView<const RtcEventVideoSendStreamConfig*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventVideoSendStreamConfig* base_event : batch) {
    rtclog2::VideoSendStreamConfig* proto_batch =
        event_stream->add_video_send_stream_configs();
    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_ssrc(base_event->config().local_ssrc);
    proto_batch->set_rtx_ssrc(base_event->config().rtx_ssrc);

    rtclog2::RtpHeaderExtensionConfig* proto_config =
        proto_batch->mutable_header_extensions();
    bool has_recognized_extensions =
        ConvertToProtoFormat(base_event->config().rtp_extensions, proto_config);
    if (!has_recognized_extensions)
      proto_batch->clear_header_extensions();
  }
}

void RtcEventLogEncoderNewFormat::EncodeIceCandidatePairConfig(
    rtc::ArrayView<const RtcEventIceCandidatePairConfig*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventIceCandidatePairConfig* base_event : batch) {
    rtclog2::IceCandidatePairConfig* proto_batch =
        event_stream->add_ice_candidate_configs();

    proto_batch->set_timestamp_ms(base_event->timestamp_ms());
    proto_batch->set_config_type(ConvertToProtoFormat(base_event->type()));
    proto_batch->set_candidate_pair_id(base_event->candidate_pair_id());
    const auto& desc = base_event->candidate_pair_desc();
    proto_batch->set_local_candidate_type(
        ConvertToProtoFormat(desc.local_candidate_type));
    proto_batch->set_local_relay_protocol(
        ConvertToProtoFormat(desc.local_relay_protocol));
    proto_batch->set_local_network_type(
        ConvertToProtoFormat(desc.local_network_type));
    proto_batch->set_local_address_family(
        ConvertToProtoFormat(desc.local_address_family));
    proto_batch->set_remote_candidate_type(
        ConvertToProtoFormat(desc.remote_candidate_type));
    proto_batch->set_remote_address_family(
        ConvertToProtoFormat(desc.remote_address_family));
    proto_batch->set_candidate_pair_protocol(
        ConvertToProtoFormat(desc.candidate_pair_protocol));
  }
  // TODO(terelius): Should we delta-compress this event type?
}

void RtcEventLogEncoderNewFormat::EncodeIceCandidatePairEvent(
    rtc::ArrayView<const RtcEventIceCandidatePair*> batch,
    rtclog2::EventStream* event_stream) {
  for (const RtcEventIceCandidatePair* base_event : batch) {
    rtclog2::IceCandidatePairEvent* proto_batch =
        event_stream->add_ice_candidate_events();

    proto_batch->set_timestamp_ms(base_event->timestamp_ms());

    proto_batch->set_event_type(ConvertToProtoFormat(base_event->type()));
    proto_batch->set_candidate_pair_id(base_event->candidate_pair_id());
    proto_batch->set_transaction_id(base_event->transaction_id());
  }
  // TODO(terelius): Should we delta-compress this event type?
}

}  // namespace webrtc
