/*
 *  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 "api/network_state_predictor.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_frame_decoded.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/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_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_NOTREACHED();
  return rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE;
}

rtclog2::FrameDecodedEvents::Codec ConvertToProtoFormat(VideoCodecType codec) {
  switch (codec) {
    case VideoCodecType::kVideoCodecGeneric:
      return rtclog2::FrameDecodedEvents::CODEC_GENERIC;
    case VideoCodecType::kVideoCodecVP8:
      return rtclog2::FrameDecodedEvents::CODEC_VP8;
    case VideoCodecType::kVideoCodecVP9:
      return rtclog2::FrameDecodedEvents::CODEC_VP9;
    case VideoCodecType::kVideoCodecAV1:
      return rtclog2::FrameDecodedEvents::CODEC_AV1;
    case VideoCodecType::kVideoCodecH264:
      return rtclog2::FrameDecodedEvents::CODEC_H264;
    case VideoCodecType::kVideoCodecMultiplex:
      // This codec type is afaik not used.
      return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
  }
  RTC_DCHECK_NOTREACHED();
  return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
}

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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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_DCHECK_NOTREACHED();
  }
  RTC_DCHECK_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 at least `packet.size()` bytes.
size_t RemoveNonAllowlistedRtcpBlocks(const rtc::Buffer& packet,
                                      uint8_t* buffer) {
  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::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, 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 allowlisted 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());
  {
    std::vector<uint8_t> buffer(base_event->packet().size());
    size_t buffer_length =
        RemoveNonAllowlistedRtcpBlocks(base_event->packet(), buffer.data());
    proto_batch->set_raw_packet(buffer.data(), 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 = RemoveNonAllowlistedRtcpBlocks(
        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->Marker());
  // TODO(terelius): Is payload type needed?
  proto_batch->set_payload_type(base_event->PayloadType());
  proto_batch->set_sequence_number(base_event->SequenceNumber());
  proto_batch->set_rtp_timestamp(base_event->Timestamp());
  proto_batch->set_ssrc(base_event->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->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->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->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->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->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->Marker();
  }
  encoded_deltas = EncodeDeltas(base_event->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->PayloadType();
  }
  encoded_deltas = EncodeDeltas(base_event->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->SequenceNumber();
  }
  encoded_deltas = EncodeDeltas(base_event->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->Timestamp();
  }
  encoded_deltas = EncodeDeltas(base_event->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->Ssrc();
  }
  encoded_deltas = EncodeDeltas(base_event->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->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->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->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->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->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->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::map<uint32_t /* SSRC */, std::vector<const RtcEventFrameDecoded*>>
        frames_decoded;
    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->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->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;
        }
        case RtcEvent::Type::FrameDecoded: {
          auto* rtc_event =
              static_cast<const RtcEventFrameDecoded* const>(it->get());
          frames_decoded[rtc_event->ssrc()].emplace_back(rtc_event);
          break;
        }
        case RtcEvent::Type::BeginV3Log:
        case RtcEvent::Type::EndV3Log:
          // These special events are written as part of starting
          // and stopping the log, and only as part of version 3 of the format.
          RTC_DCHECK_NOTREACHED();
          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);
    for (const auto& kv : frames_decoded) {
      EncodeFramesDecoded(kv.second, &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 (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 (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::EncodeFramesDecoded(
    rtc::ArrayView<const RtcEventFrameDecoded* const> batch,
    rtclog2::EventStream* event_stream) {
  if (batch.empty()) {
    return;
  }
  const RtcEventFrameDecoded* const base_event = batch[0];
  rtclog2::FrameDecodedEvents* proto_batch =
      event_stream->add_frame_decoded_events();
  proto_batch->set_timestamp_ms(base_event->timestamp_ms());
  proto_batch->set_ssrc(base_event->ssrc());
  proto_batch->set_render_time_ms(base_event->render_time_ms());
  proto_batch->set_width(base_event->width());
  proto_batch->set_height(base_event->height());
  proto_batch->set_codec(ConvertToProtoFormat(base_event->codec()));
  proto_batch->set_qp(base_event->qp());

  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 RtcEventFrameDecoded* 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);
  }

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

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

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

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

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

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

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
