Create RtcEventLogEncoderLegacy

We're moving to an RtcEventLog interface that accepts std::unique_ptr<EventLog> and stores the event for encoding when encoding becomes necessary, rather than before. This will be useful while we maintain the legacy (current) encoding alongside the new encoding on which we're working.

This CL introduces RtcEventLogEncoderLegacy, which takes provides the encoding currently done by RtcEventLogImpl. After this, we can modify RtcEventLogImpl to use a dynamically chosen encoding, allowing us to easily choose between the current encoding and the new one on which we're working.

BUG=webrtc:8111
TBR=stefan@webrtc.org

Change-Id: I3dde7e222a40a117549a094a59b04219467f490a
Reviewed-on: https://webrtc-review.googlesource.com/1364
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20116}
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index e56111a..a654fc4 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -78,6 +78,9 @@
 
 rtc_static_library("rtc_event_log_impl") {
   sources = [
+    "rtc_event_log/encoder/rtc_event_log_encoder.h",
+    "rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc",
+    "rtc_event_log/encoder/rtc_event_log_encoder_legacy.h",
     "rtc_event_log/rtc_event_log.cc",
     "rtc_event_log/rtc_event_log_factory.cc",
     "rtc_event_log/rtc_event_log_factory.h",
@@ -146,7 +149,10 @@
   if (rtc_include_tests) {
     rtc_source_set("rtc_event_log_tests") {
       testonly = true
+      assert(rtc_enable_protobuf)
+      defines = [ "ENABLE_RTC_EVENT_LOG" ]
       sources = [
+        "rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc",
         "rtc_event_log/rtc_event_log_unittest.cc",
         "rtc_event_log/rtc_event_log_unittest_helper.cc",
         "rtc_event_log/rtc_event_log_unittest_helper.h",
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
new file mode 100644
index 0000000..3580d9c
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_H_
+#define LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_H_
+
+#include <string>
+
+#include "logging/rtc_event_log/events/rtc_event.h"
+
+namespace webrtc {
+class RtcEventLogEncoder {
+ public:
+  virtual ~RtcEventLogEncoder() = default;
+
+  virtual std::string Encode(const RtcEvent& event) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_H_
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
new file mode 100644
index 0000000..47b4c1e
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -0,0 +1,571 @@
+/*
+ *  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_legacy.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_logging_started.h"
+#include "logging/rtc_event_log/events/rtc_event_logging_stopped.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_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_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_packet.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/ignore_wundef.h"
+#include "rtc_base/logging.h"
+
+#ifdef ENABLE_RTC_EVENT_LOG
+
+// *.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_log.pb.h"
+#else
+#include "logging/rtc_event_log/rtc_event_log.pb.h"
+#endif
+RTC_POP_IGNORING_WUNDEF()
+
+namespace webrtc {
+
+namespace {
+rtclog::DelayBasedBweUpdate::DetectorState ConvertDetectorState(
+    BandwidthUsage state) {
+  switch (state) {
+    case BandwidthUsage::kBwNormal:
+      return rtclog::DelayBasedBweUpdate::BWE_NORMAL;
+    case BandwidthUsage::kBwUnderusing:
+      return rtclog::DelayBasedBweUpdate::BWE_UNDERUSING;
+    case BandwidthUsage::kBwOverusing:
+      return rtclog::DelayBasedBweUpdate::BWE_OVERUSING;
+    case BandwidthUsage::kLast:
+      RTC_NOTREACHED();
+  }
+  RTC_NOTREACHED();
+  return rtclog::DelayBasedBweUpdate::BWE_NORMAL;
+}
+
+rtclog::BweProbeResult::ResultType ConvertProbeResultType(
+    ProbeFailureReason failure_reason) {
+  switch (failure_reason) {
+    case ProbeFailureReason::kInvalidSendReceiveInterval:
+      return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL;
+    case ProbeFailureReason::kInvalidSendReceiveRatio:
+      return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO;
+    case ProbeFailureReason::kTimeout:
+      return rtclog::BweProbeResult::TIMEOUT;
+    case ProbeFailureReason::kLast:
+      RTC_NOTREACHED();
+  }
+  RTC_NOTREACHED();
+  return rtclog::BweProbeResult::SUCCESS;
+}
+
+rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) {
+  switch (rtcp_mode) {
+    case RtcpMode::kCompound:
+      return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
+    case RtcpMode::kReducedSize:
+      return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE;
+    case RtcpMode::kOff:
+      RTC_NOTREACHED();
+  }
+  RTC_NOTREACHED();
+  return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
+}
+}  // namespace
+
+std::string RtcEventLogEncoderLegacy::Encode(const RtcEvent& event) {
+  switch (event.GetType()) {
+    case RtcEvent::Type::AudioNetworkAdaptation: {
+      auto& rtc_event =
+          static_cast<const RtcEventAudioNetworkAdaptation&>(event);
+      return EncodeAudioNetworkAdaptation(rtc_event);
+    }
+
+    case RtcEvent::Type::AudioPlayout: {
+      auto& rtc_event = static_cast<const RtcEventAudioPlayout&>(event);
+      return EncodeAudioPlayout(rtc_event);
+    }
+
+    case RtcEvent::Type::AudioReceiveStreamConfig: {
+      auto& rtc_event =
+          static_cast<const RtcEventAudioReceiveStreamConfig&>(event);
+      return EncodeAudioReceiveStreamConfig(rtc_event);
+    }
+
+    case RtcEvent::Type::AudioSendStreamConfig: {
+      auto& rtc_event =
+          static_cast<const RtcEventAudioSendStreamConfig&>(event);
+      return EncodeAudioSendStreamConfig(rtc_event);
+    }
+
+    case RtcEvent::Type::BweUpdateDelayBased: {
+      auto& rtc_event = static_cast<const RtcEventBweUpdateDelayBased&>(event);
+      return EncodeBweUpdateDelayBased(rtc_event);
+    }
+
+    case RtcEvent::Type::BweUpdateLossBased: {
+      auto& rtc_event = static_cast<const RtcEventBweUpdateLossBased&>(event);
+      return EncodeBweUpdateLossBased(rtc_event);
+    }
+
+    case RtcEvent::Type::LoggingStarted: {
+      auto& rtc_event = static_cast<const RtcEventLoggingStarted&>(event);
+      return EncodeLoggingStarted(rtc_event);
+    }
+
+    case RtcEvent::Type::LoggingStopped: {
+      auto& rtc_event = static_cast<const RtcEventLoggingStopped&>(event);
+      return EncodeLoggingStopped(rtc_event);
+    }
+
+    case RtcEvent::Type::ProbeClusterCreated: {
+      auto& rtc_event = static_cast<const RtcEventProbeClusterCreated&>(event);
+      return EncodeProbeClusterCreated(rtc_event);
+    }
+
+    case RtcEvent::Type::ProbeResultFailure: {
+      auto& rtc_event = static_cast<const RtcEventProbeResultFailure&>(event);
+      return EncodeProbeResultFailure(rtc_event);
+    }
+
+    case RtcEvent::Type::ProbeResultSuccess: {
+      auto& rtc_event = static_cast<const RtcEventProbeResultSuccess&>(event);
+      return EncodeProbeResultSuccess(rtc_event);
+    }
+
+    case RtcEvent::Type::RtcpPacketIncoming: {
+      auto& rtc_event = static_cast<const RtcEventRtcpPacketIncoming&>(event);
+      return EncodeRtcpPacketIncoming(rtc_event);
+    }
+
+    case RtcEvent::Type::RtcpPacketOutgoing: {
+      auto& rtc_event = static_cast<const RtcEventRtcpPacketOutgoing&>(event);
+      return EncodeRtcpPacketOutgoing(rtc_event);
+    }
+
+    case RtcEvent::Type::RtpPacketIncoming: {
+      auto& rtc_event = static_cast<const RtcEventRtpPacketIncoming&>(event);
+      return EncodeRtpPacketIncoming(rtc_event);
+    }
+
+    case RtcEvent::Type::RtpPacketOutgoing: {
+      auto& rtc_event = static_cast<const RtcEventRtpPacketOutgoing&>(event);
+      return EncodeRtpPacketOutgoing(rtc_event);
+    }
+
+    case RtcEvent::Type::VideoReceiveStreamConfig: {
+      auto& rtc_event =
+          static_cast<const RtcEventVideoReceiveStreamConfig&>(event);
+      return EncodeVideoReceiveStreamConfig(rtc_event);
+    }
+
+    case RtcEvent::Type::VideoSendStreamConfig: {
+      auto& rtc_event =
+          static_cast<const RtcEventVideoSendStreamConfig&>(event);
+      return EncodeVideoSendStreamConfig(rtc_event);
+    }
+  }
+
+  int event_type = static_cast<int>(event.GetType());
+  RTC_NOTREACHED() << "Unknown event type (" << event_type << ")";
+  return "";
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeAudioNetworkAdaptation(
+    const RtcEventAudioNetworkAdaptation& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT);
+
+  auto audio_network_adaptation =
+      rtclog_event.mutable_audio_network_adaptation();
+  if (event.config_->bitrate_bps)
+    audio_network_adaptation->set_bitrate_bps(*event.config_->bitrate_bps);
+  if (event.config_->frame_length_ms)
+    audio_network_adaptation->set_frame_length_ms(
+        *event.config_->frame_length_ms);
+  if (event.config_->uplink_packet_loss_fraction) {
+    audio_network_adaptation->set_uplink_packet_loss_fraction(
+        *event.config_->uplink_packet_loss_fraction);
+  }
+  if (event.config_->enable_fec)
+    audio_network_adaptation->set_enable_fec(*event.config_->enable_fec);
+  if (event.config_->enable_dtx)
+    audio_network_adaptation->set_enable_dtx(*event.config_->enable_dtx);
+  if (event.config_->num_channels)
+    audio_network_adaptation->set_num_channels(*event.config_->num_channels);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeAudioPlayout(
+    const RtcEventAudioPlayout& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
+
+  auto playout_event = rtclog_event.mutable_audio_playout_event();
+  playout_event->set_local_ssrc(event.ssrc_);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeAudioReceiveStreamConfig(
+    const RtcEventAudioReceiveStreamConfig& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT);
+
+  rtclog::AudioReceiveConfig* receiver_config =
+      rtclog_event.mutable_audio_receiver_config();
+  receiver_config->set_remote_ssrc(event.config_->remote_ssrc);
+  receiver_config->set_local_ssrc(event.config_->local_ssrc);
+
+  for (const auto& e : event.config_->rtp_extensions) {
+    rtclog::RtpHeaderExtension* extension =
+        receiver_config->add_header_extensions();
+    extension->set_name(e.uri);
+    extension->set_id(e.id);
+  }
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeAudioSendStreamConfig(
+    const RtcEventAudioSendStreamConfig& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::AUDIO_SENDER_CONFIG_EVENT);
+
+  rtclog::AudioSendConfig* sender_config =
+      rtclog_event.mutable_audio_sender_config();
+
+  sender_config->set_ssrc(event.config_->local_ssrc);
+
+  for (const auto& e : event.config_->rtp_extensions) {
+    rtclog::RtpHeaderExtension* extension =
+        sender_config->add_header_extensions();
+    extension->set_name(e.uri);
+    extension->set_id(e.id);
+  }
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeBweUpdateDelayBased(
+    const RtcEventBweUpdateDelayBased& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::DELAY_BASED_BWE_UPDATE);
+
+  auto bwe_event = rtclog_event.mutable_delay_based_bwe_update();
+  bwe_event->set_bitrate_bps(event.bitrate_bps_);
+  bwe_event->set_detector_state(ConvertDetectorState(event.detector_state_));
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeBweUpdateLossBased(
+    const RtcEventBweUpdateLossBased& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::LOSS_BASED_BWE_UPDATE);
+
+  auto bwe_event = rtclog_event.mutable_loss_based_bwe_update();
+  bwe_event->set_bitrate_bps(event.bitrate_bps_);
+  bwe_event->set_fraction_loss(event.fraction_loss_);
+  bwe_event->set_total_packets(event.total_packets_);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeLoggingStarted(
+    const RtcEventLoggingStarted& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::LOG_START);
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeLoggingStopped(
+    const RtcEventLoggingStopped& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::LOG_END);
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeProbeClusterCreated(
+    const RtcEventProbeClusterCreated& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT);
+
+  auto probe_cluster = rtclog_event.mutable_probe_cluster();
+  probe_cluster->set_id(event.id_);
+  probe_cluster->set_bitrate_bps(event.bitrate_bps_);
+  probe_cluster->set_min_packets(event.min_probes_);
+  probe_cluster->set_min_bytes(event.min_bytes_);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeProbeResultFailure(
+    const RtcEventProbeResultFailure& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::BWE_PROBE_RESULT_EVENT);
+
+  auto probe_result = rtclog_event.mutable_probe_result();
+  probe_result->set_id(event.id_);
+  probe_result->set_result(ConvertProbeResultType(event.failure_reason_));
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeProbeResultSuccess(
+    const RtcEventProbeResultSuccess& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::BWE_PROBE_RESULT_EVENT);
+
+  auto probe_result = rtclog_event.mutable_probe_result();
+  probe_result->set_id(event.id_);
+  probe_result->set_result(rtclog::BweProbeResult::SUCCESS);
+  probe_result->set_bitrate_bps(event.bitrate_bps_);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtcpPacketIncoming(
+    const RtcEventRtcpPacketIncoming& event) {
+  return EncodeRtcpPacket(event.timestamp_us_, event.packet_, true);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtcpPacketOutgoing(
+    const RtcEventRtcpPacketOutgoing& event) {
+  return EncodeRtcpPacket(event.timestamp_us_, event.packet_, false);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtpPacketIncoming(
+    const RtcEventRtpPacketIncoming& event) {
+  return EncodeRtpPacket(event.timestamp_us_, event.header_,
+                         event.packet_length_, PacedPacketInfo::kNotAProbe,
+                         true);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtpPacketOutgoing(
+    const RtcEventRtpPacketOutgoing& event) {
+  return EncodeRtpPacket(event.timestamp_us_, event.header_,
+                         event.packet_length_, event.probe_cluster_id_, false);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeVideoReceiveStreamConfig(
+    const RtcEventVideoReceiveStreamConfig& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
+
+  rtclog::VideoReceiveConfig* receiver_config =
+      rtclog_event.mutable_video_receiver_config();
+  receiver_config->set_remote_ssrc(event.config_->remote_ssrc);
+  receiver_config->set_local_ssrc(event.config_->local_ssrc);
+
+  // TODO(perkj): Add field for rsid.
+  receiver_config->set_rtcp_mode(ConvertRtcpMode(event.config_->rtcp_mode));
+  receiver_config->set_remb(event.config_->remb);
+
+  for (const auto& e : event.config_->rtp_extensions) {
+    rtclog::RtpHeaderExtension* extension =
+        receiver_config->add_header_extensions();
+    extension->set_name(e.uri);
+    extension->set_id(e.id);
+  }
+
+  for (const auto& d : event.config_->codecs) {
+    rtclog::DecoderConfig* decoder = receiver_config->add_decoders();
+    decoder->set_name(d.payload_name);
+    decoder->set_payload_type(d.payload_type);
+    if (d.rtx_payload_type != 0) {
+      rtclog::RtxMap* rtx = receiver_config->add_rtx_map();
+      rtx->set_payload_type(d.payload_type);
+      rtx->mutable_config()->set_rtx_ssrc(event.config_->rtx_ssrc);
+      rtx->mutable_config()->set_rtx_payload_type(d.rtx_payload_type);
+    }
+  }
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeVideoSendStreamConfig(
+    const RtcEventVideoSendStreamConfig& event) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(event.timestamp_us_);
+  rtclog_event.set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
+
+  rtclog::VideoSendConfig* sender_config =
+      rtclog_event.mutable_video_sender_config();
+
+  // TODO(perkj): rtclog::VideoSendConfig should only contain one SSRC.
+  sender_config->add_ssrcs(event.config_->local_ssrc);
+  if (event.config_->rtx_ssrc != 0) {
+    sender_config->add_rtx_ssrcs(event.config_->rtx_ssrc);
+  }
+
+  for (const auto& e : event.config_->rtp_extensions) {
+    rtclog::RtpHeaderExtension* extension =
+        sender_config->add_header_extensions();
+    extension->set_name(e.uri);
+    extension->set_id(e.id);
+  }
+
+  // TODO(perkj): rtclog::VideoSendConfig should contain many possible codec
+  // configurations.
+  for (const auto& codec : event.config_->codecs) {
+    sender_config->set_rtx_payload_type(codec.rtx_payload_type);
+    rtclog::EncoderConfig* encoder = sender_config->mutable_encoder();
+    encoder->set_name(codec.payload_name);
+    encoder->set_payload_type(codec.payload_type);
+
+    if (event.config_->codecs.size() > 1) {
+      LOG(WARNING) << "LogVideoSendStreamConfig currently only supports one "
+                   << "codec. Logging codec :" << codec.payload_name;
+      break;
+    }
+  }
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtcpPacket(
+    int64_t timestamp_us,
+    const rtc::Buffer& packet,
+    bool is_incoming) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(timestamp_us);
+  rtclog_event.set_type(rtclog::Event::RTCP_EVENT);
+  rtclog_event.mutable_rtcp_packet()->set_incoming(is_incoming);
+
+  rtcp::CommonHeader header;
+  const uint8_t* block_begin = packet.data();
+  const uint8_t* packet_end = packet.data() + packet.size();
+  RTC_DCHECK(packet.size() <= IP_PACKET_SIZE);
+  uint8_t buffer[IP_PACKET_SIZE];
+  uint32_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();
+    uint32_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.
+        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;
+  }
+  rtclog_event.mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::EncodeRtpPacket(
+    int64_t timestamp_us,
+    const webrtc::RtpPacket& header,
+    size_t packet_length,
+    int probe_cluster_id,
+    bool is_incoming) {
+  rtclog::Event rtclog_event;
+  rtclog_event.set_timestamp_us(timestamp_us);
+  rtclog_event.set_type(rtclog::Event::RTP_EVENT);
+
+  rtclog_event.mutable_rtp_packet()->set_incoming(is_incoming);
+  rtclog_event.mutable_rtp_packet()->set_packet_length(packet_length);
+  rtclog_event.mutable_rtp_packet()->set_header(header.data(), header.size());
+  if (probe_cluster_id != PacedPacketInfo::kNotAProbe) {
+    RTC_DCHECK(!is_incoming);
+    rtclog_event.mutable_rtp_packet()->set_probe_cluster_id(probe_cluster_id);
+  }
+
+  return Serialize(&rtclog_event);
+}
+
+std::string RtcEventLogEncoderLegacy::Serialize(rtclog::Event* event) {
+  // Even though we're only serializing a single event during this call, what
+  // we intend to get is a list of events, with a tag and length preceding
+  // each actual event. To produce that, we serialize a list of a single event.
+  // If we later concatenate several results from this function, the result will
+  // be a proper concatenation of all those events.
+
+  rtclog::EventStream event_stream;
+  event_stream.add_stream();
+
+  // As a tweak, we swap the new event into the event-stream, write that to
+  // file, then swap back. This saves on some copying, while making sure that
+  // the caller wouldn't be surprised by Serialize() modifying the object.
+  rtclog::Event* output_event = event_stream.mutable_stream(0);
+  output_event->Swap(event);
+
+  std::string output_string = event_stream.SerializeAsString();
+  RTC_DCHECK(!output_string.empty());
+
+  // When the function returns, the original Event will be unchanged.
+  output_event->Swap(event);
+
+  return output_string;
+}
+
+}  // namespace webrtc
+
+#endif  // ENABLE_RTC_EVENT_LOG
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
new file mode 100644
index 0000000..b0909e2
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
@@ -0,0 +1,97 @@
+/*
+ *  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.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_LEGACY_H_
+#define LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_LEGACY_H_
+
+#include <memory>
+#include <string>
+
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder.h"
+#include "rtc_base/buffer.h"
+
+#if defined(ENABLE_RTC_EVENT_LOG)
+
+namespace webrtc {
+
+namespace rtclog {
+class Event;  // Auto-generated from protobuf.
+}  // namespace rtclog
+
+class RtcEventAudioNetworkAdaptation;
+class RtcEventAudioPlayout;
+class RtcEventAudioReceiveStreamConfig;
+class RtcEventAudioSendStreamConfig;
+class RtcEventBweUpdateDelayBased;
+class RtcEventBweUpdateLossBased;
+class RtcEventLoggingStarted;
+class RtcEventLoggingStopped;
+class RtcEventProbeClusterCreated;
+class RtcEventProbeResultFailure;
+class RtcEventProbeResultSuccess;
+class RtcEventRtcpPacketIncoming;
+class RtcEventRtcpPacketOutgoing;
+class RtcEventRtpPacketIncoming;
+class RtcEventRtpPacketOutgoing;
+class RtcEventVideoReceiveStreamConfig;
+class RtcEventVideoSendStreamConfig;
+class RtpPacket;
+
+class RtcEventLogEncoderLegacy final : public RtcEventLogEncoder {
+ public:
+  ~RtcEventLogEncoderLegacy() override = default;
+
+  std::string Encode(const RtcEvent& event) override;
+
+ private:
+  // Encoding entry-point for the various RtcEvent subclasses.
+  std::string EncodeAudioNetworkAdaptation(
+      const RtcEventAudioNetworkAdaptation& event);
+  std::string EncodeAudioPlayout(const RtcEventAudioPlayout& event);
+  std::string EncodeAudioReceiveStreamConfig(
+      const RtcEventAudioReceiveStreamConfig& event);
+  std::string EncodeAudioSendStreamConfig(
+      const RtcEventAudioSendStreamConfig& event);
+  std::string EncodeBweUpdateDelayBased(
+      const RtcEventBweUpdateDelayBased& event);
+  std::string EncodeBweUpdateLossBased(const RtcEventBweUpdateLossBased& event);
+  std::string EncodeLoggingStarted(const RtcEventLoggingStarted& event);
+  std::string EncodeLoggingStopped(const RtcEventLoggingStopped& event);
+  std::string EncodeProbeClusterCreated(
+      const RtcEventProbeClusterCreated& event);
+  std::string EncodeProbeResultFailure(const RtcEventProbeResultFailure& event);
+  std::string EncodeProbeResultSuccess(const RtcEventProbeResultSuccess&);
+  std::string EncodeRtcpPacketIncoming(const RtcEventRtcpPacketIncoming& event);
+  std::string EncodeRtcpPacketOutgoing(const RtcEventRtcpPacketOutgoing& event);
+  std::string EncodeRtpPacketIncoming(const RtcEventRtpPacketIncoming& event);
+  std::string EncodeRtpPacketOutgoing(const RtcEventRtpPacketOutgoing& event);
+  std::string EncodeVideoReceiveStreamConfig(
+      const RtcEventVideoReceiveStreamConfig& event);
+  std::string EncodeVideoSendStreamConfig(
+      const RtcEventVideoSendStreamConfig& event);
+
+  // RTCP/RTP are handled similarly for incoming/outgoing.
+  std::string EncodeRtcpPacket(int64_t timestamp_us,
+                               const rtc::Buffer& packet,
+                               bool is_incoming);
+  std::string EncodeRtpPacket(int64_t timestamp_us,
+                              const RtpPacket& header,
+                              size_t packet_length,
+                              int probe_cluster_id,
+                              bool is_incoming);
+
+  std::string Serialize(rtclog::Event* event);
+};
+
+}  // namespace webrtc
+
+#endif  // ENABLE_RTC_EVENT_LOG
+
+#endif  // LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_LEGACY_H_
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
new file mode 100644
index 0000000..0423f57
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -0,0 +1,537 @@
+/*
+ *  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 <limits>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "api/rtpparameters.h"  // RtpExtension
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.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_logging_started.h"
+#include "logging/rtc_event_log/events/rtc_event_logging_stopped.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_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_event_log_parser.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/source/rtcp_packet/bye.h"  // Arbitrary RTCP message.
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/ptr_util.h"
+#include "rtc_base/random.h"
+#include "rtc_base/safe_conversions.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+const char* const arbitrary_uri =  // Just a recognized URI.
+    "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
+}  // namespace
+
+class RtcEventLogEncoderTest : public testing::TestWithParam<int> {
+ protected:
+  RtcEventLogEncoderTest()
+      : encoder_(new RtcEventLogEncoderLegacy), prng_(GetParam()) {}
+  ~RtcEventLogEncoderTest() override = default;
+
+  // ANA events have some optional fields, so we want to make sure that we get
+  // correct behavior both when all of the values are there, as well as when
+  // only some.
+  void TestRtcEventAudioNetworkAdaptation(
+      std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config);
+
+  // These help prevent code duplication between incoming/outgoing variants.
+  void TestRtcEventRtcpPacket(PacketDirection direction);
+  void TestRtcEventRtpPacket(PacketDirection direction);
+
+  int RandomInt() {
+    // Don't run this on a SNES.
+    static_assert(8 * sizeof(int) >= 32, "Don't run this on a SNES.");
+    int32_t rand = prng_.Rand(0, std::numeric_limits<int32_t>::max());
+    return rtc::saturated_cast<int>(rand);
+  }
+
+  int RandomPositiveInt() {
+    int32_t rand = prng_.Rand(1, std::numeric_limits<int32_t>::max());
+    return rtc::saturated_cast<int>(rand);
+  }
+
+  uint32_t RandomSsrc() {
+    return prng_.Rand(std::numeric_limits<uint32_t>::max());
+  }
+
+  int RandomRtpExtensionId() {
+    return static_cast<int>(
+        prng_.Rand(RtpExtension::kMinId, RtpExtension::kMaxId));
+  }
+
+  int RandomBitrate() { return RandomInt(); }
+
+  // TODO(eladalon): Once we have more than once possible encoder, parameterize
+  // encoder selection.
+  std::unique_ptr<RtcEventLogEncoder> encoder_;
+  ParsedRtcEventLog parsed_log_;
+  Random prng_;
+};
+
+void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
+    std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config) {
+  auto original_runtime_config = *runtime_config;
+  auto event = rtc::MakeUnique<RtcEventAudioNetworkAdaptation>(
+      std::move(runtime_config));
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT);
+
+  AudioEncoderRuntimeConfig parsed_runtime_config;
+  parsed_log_.GetAudioNetworkAdaptation(0, &parsed_runtime_config);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_runtime_config, original_runtime_config);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationBitrate) {
+  auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+  const int bitrate_bps = RandomBitrate();
+  runtime_config->bitrate_bps = rtc::Optional<int>(bitrate_bps);
+  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFrameLength) {
+  auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+  const int frame_length_ms = prng_.Rand(1, 1000);
+  runtime_config->frame_length_ms = rtc::Optional<int>(frame_length_ms);
+  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationPacketLoss) {
+  // To simplify the test, we just check powers of two.
+  const float plr = std::pow(0.5f, prng_.Rand(1, 8));
+  auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+  runtime_config->uplink_packet_loss_fraction = rtc::Optional<float>(plr);
+  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFec) {
+  // The test might be trivially passing for one of the two boolean values, so
+  // for safety's sake, we test both.
+  for (bool fec_enabled : {false, true}) {
+    auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+    runtime_config->enable_fec = rtc::Optional<bool>(fec_enabled);
+    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+  }
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationDtx) {
+  // The test might be trivially passing for one of the two boolean values, so
+  // for safety's sake, we test both.
+  for (bool dtx_enabled : {false, true}) {
+    auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+    runtime_config->enable_dtx = rtc::Optional<bool>(dtx_enabled);
+    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+  }
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationChannels) {
+  // The test might be trivially passing for one of the two possible values, so
+  // for safety's sake, we test both.
+  for (size_t channels : {1, 2}) {
+    auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+    runtime_config->num_channels = rtc::Optional<size_t>(channels);
+    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+  }
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationAll) {
+  const int bitrate_bps = RandomBitrate();
+  const int frame_length_ms = prng_.Rand(1, 1000);
+  const float plr = std::pow(0.5f, prng_.Rand(1, 8));
+  for (bool fec_enabled : {false, true}) {
+    for (bool dtx_enabled : {false, true}) {
+      for (size_t channels : {1, 2}) {
+        auto runtime_config = rtc::MakeUnique<AudioEncoderRuntimeConfig>();
+        runtime_config->bitrate_bps = rtc::Optional<int>(bitrate_bps);
+        runtime_config->frame_length_ms = rtc::Optional<int>(frame_length_ms);
+        runtime_config->uplink_packet_loss_fraction = rtc::Optional<float>(plr);
+        runtime_config->enable_fec = rtc::Optional<bool>(fec_enabled);
+        runtime_config->enable_dtx = rtc::Optional<bool>(dtx_enabled);
+        runtime_config->num_channels = rtc::Optional<size_t>(channels);
+
+        TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
+      }
+    }
+  }
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
+  const uint32_t ssrc = RandomSsrc();
+  auto event = rtc::MakeUnique<RtcEventAudioPlayout>(ssrc);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::AUDIO_PLAYOUT_EVENT);
+
+  uint32_t parsed_ssrc;
+  parsed_log_.GetAudioPlayout(0, &parsed_ssrc);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_ssrc, ssrc);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
+  auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
+  stream_config->local_ssrc = RandomSsrc();
+  stream_config->remote_ssrc = RandomSsrc();
+  // TODO(eladalon): !!! Validate this, here and elsewhere.
+  stream_config->rtp_extensions.push_back(
+      RtpExtension(arbitrary_uri, RandomRtpExtensionId()));
+
+  auto original_stream_config = *stream_config;
+
+  auto event = rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>(
+      std::move(stream_config));
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT);
+
+  auto parsed_event = parsed_log_.GetAudioReceiveConfig(0);
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_event, original_stream_config);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
+  auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
+  stream_config->local_ssrc = RandomSsrc();
+  stream_config->rtp_extensions.push_back(
+      RtpExtension(arbitrary_uri, RandomRtpExtensionId()));
+
+  auto original_stream_config = *stream_config;
+
+  auto event =
+      rtc::MakeUnique<RtcEventAudioSendStreamConfig>(std::move(stream_config));
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT);
+
+  auto parsed_event = parsed_log_.GetAudioSendConfig(0);
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_event, original_stream_config);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
+  const int32_t bitrate_bps = RandomBitrate();
+  const BandwidthUsage detector_state = static_cast<BandwidthUsage>(
+      prng_.Rand(0, static_cast<int32_t>(BandwidthUsage::kLast) - 1));
+  auto event =
+      rtc::MakeUnique<RtcEventBweUpdateDelayBased>(bitrate_bps, detector_state);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::DELAY_BASED_BWE_UPDATE);
+
+  auto parsed_event = parsed_log_.GetDelayBasedBweUpdate(0);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_event.bitrate_bps, bitrate_bps);
+  EXPECT_EQ(parsed_event.detector_state, detector_state);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
+  const int32_t bitrate_bps = RandomBitrate();
+  const uint8_t fraction_loss = rtc::dchecked_cast<uint8_t>(
+      prng_.Rand(0, std::numeric_limits<uint8_t>::max()));
+  const int32_t total_packets = RandomInt();
+
+  auto event = rtc::MakeUnique<RtcEventBweUpdateLossBased>(
+      bitrate_bps, fraction_loss, total_packets);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::LOSS_BASED_BWE_UPDATE);
+
+  int32_t parsed_bitrate_bps;
+  uint8_t parsed_fraction_loss;
+  int32_t parsed_total_packets;
+  parsed_log_.GetLossBasedBweUpdate(
+      0, &parsed_bitrate_bps, &parsed_fraction_loss, &parsed_total_packets);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_bitrate_bps, bitrate_bps);
+  EXPECT_EQ(parsed_fraction_loss, fraction_loss);
+  EXPECT_EQ(parsed_total_packets, total_packets);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
+  auto event = rtc::MakeUnique<RtcEventLoggingStarted>();
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::LOG_START);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
+  auto event = rtc::MakeUnique<RtcEventLoggingStopped>();
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::LOG_END);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
+  const int id = RandomPositiveInt();
+  const int bitrate_bps = RandomBitrate();
+  const int min_probes = RandomPositiveInt();
+  const int min_bytes = RandomPositiveInt();
+
+  auto event = rtc::MakeUnique<RtcEventProbeClusterCreated>(
+      id, bitrate_bps, min_probes, min_bytes);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT);
+
+  auto parsed_event = parsed_log_.GetBweProbeClusterCreated(0);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.bitrate_bps), bitrate_bps);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.min_packets), min_probes);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.min_bytes), min_bytes);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
+  const int id = RandomPositiveInt();
+  const ProbeFailureReason failure_reason = static_cast<ProbeFailureReason>(
+      prng_.Rand(0, static_cast<int32_t>(ProbeFailureReason::kLast) - 1));
+
+  auto event = rtc::MakeUnique<RtcEventProbeResultFailure>(id, failure_reason);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT);
+
+  auto parsed_event = parsed_log_.GetBweProbeResult(0);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
+  ASSERT_FALSE(parsed_event.bitrate_bps);
+  ASSERT_TRUE(parsed_event.failure_reason);
+  EXPECT_EQ(parsed_event.failure_reason, failure_reason);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
+  const int id = RandomPositiveInt();
+  const int bitrate_bps = RandomBitrate();
+
+  auto event = rtc::MakeUnique<RtcEventProbeResultSuccess>(id, bitrate_bps);
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT);
+
+  auto parsed_event = parsed_log_.GetBweProbeResult(0);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(rtc::dchecked_cast<int>(parsed_event.id), id);
+  ASSERT_TRUE(parsed_event.bitrate_bps);
+  EXPECT_EQ(parsed_event.bitrate_bps, bitrate_bps);
+  ASSERT_FALSE(parsed_event.failure_reason);
+}
+
+void RtcEventLogEncoderTest::TestRtcEventRtcpPacket(PacketDirection direction) {
+  rtcp::Bye bye_packet;  // Arbitrarily chosen RTCP packet type.
+  bye_packet.SetReason("a man's reach should exceed his grasp");
+  auto rtcp_packet = bye_packet.Build();
+
+  std::unique_ptr<RtcEvent> event;
+  if (direction == PacketDirection::kIncomingPacket) {
+    event = rtc::MakeUnique<RtcEventRtcpPacketIncoming>(rtcp_packet);
+  } else {
+    event = rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(rtcp_packet);
+  }
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::RTCP_EVENT);
+
+  PacketDirection parsed_direction;
+  uint8_t parsed_packet[IP_PACKET_SIZE];  // "Parsed" = after event-encoding.
+  size_t parsed_packet_length;
+  parsed_log_.GetRtcpPacket(0, &parsed_direction, parsed_packet,
+                            &parsed_packet_length);
+
+  EXPECT_EQ(parsed_direction, direction);
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  ASSERT_EQ(parsed_packet_length, rtcp_packet.size());
+  ASSERT_EQ(memcmp(parsed_packet, rtcp_packet.data(), parsed_packet_length), 0);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
+  TestRtcEventRtcpPacket(PacketDirection::kIncomingPacket);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
+  TestRtcEventRtcpPacket(PacketDirection::kOutgoingPacket);
+}
+
+void RtcEventLogEncoderTest::TestRtcEventRtpPacket(PacketDirection direction) {
+  const int probe_cluster_id = RandomPositiveInt();
+
+  std::unique_ptr<RtpPacketReceived> packet_received;
+  std::unique_ptr<RtpPacketToSend> packet_to_send;
+  RtpPacket* packet;
+  if (direction == PacketDirection::kIncomingPacket) {
+    packet_received = rtc::MakeUnique<RtpPacketReceived>();
+    packet = packet_received.get();
+  } else {
+    packet_to_send = rtc::MakeUnique<RtpPacketToSend>(nullptr);
+    packet = packet_to_send.get();
+  }
+  packet->SetSsrc(RandomSsrc());
+  packet->SetSequenceNumber(static_cast<uint16_t>(RandomInt()));
+  packet->SetPayloadSize(prng_.Rand(0u, 1000u));
+
+  std::unique_ptr<RtcEvent> event;
+  if (direction == PacketDirection::kIncomingPacket) {
+    event = rtc::MakeUnique<RtcEventRtpPacketIncoming>(*packet_received);
+  } else {
+    event = rtc::MakeUnique<RtcEventRtpPacketOutgoing>(*packet_to_send,
+                                                       probe_cluster_id);
+  }
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0), ParsedRtcEventLog::RTP_EVENT);
+
+  PacketDirection parsed_direction;
+  uint8_t parsed_rtp_header[IP_PACKET_SIZE];
+  size_t parsed_header_length;
+  size_t parsed_total_length;
+  int parsed_probe_cluster_id;
+  parsed_log_.GetRtpHeader(0, &parsed_direction, parsed_rtp_header,
+                           &parsed_header_length, &parsed_total_length,
+                           &parsed_probe_cluster_id);
+
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_direction, direction);
+  if (parsed_direction == PacketDirection::kOutgoingPacket) {
+    EXPECT_EQ(parsed_probe_cluster_id, probe_cluster_id);
+  }
+  EXPECT_EQ(memcmp(parsed_rtp_header, packet->data(), parsed_header_length), 0);
+  EXPECT_EQ(parsed_header_length, packet->headers_size());
+  EXPECT_EQ(parsed_total_length, packet->size());
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
+  TestRtcEventRtpPacket(PacketDirection::kIncomingPacket);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
+  TestRtcEventRtpPacket(PacketDirection::kOutgoingPacket);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
+  auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
+  stream_config->local_ssrc = RandomSsrc();
+  stream_config->remote_ssrc = RandomSsrc();
+  stream_config->rtcp_mode = RtcpMode::kCompound;
+  stream_config->remb = prng_.Rand<bool>();
+  stream_config->rtp_extensions.push_back(
+      RtpExtension(arbitrary_uri, RandomRtpExtensionId()));
+  stream_config->codecs.emplace_back("CODEC", 122, 7);
+
+  auto original_stream_config = *stream_config;
+
+  auto event = rtc::MakeUnique<RtcEventVideoReceiveStreamConfig>(
+      std::move(stream_config));
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT);
+
+  auto parsed_event = parsed_log_.GetVideoReceiveConfig(0);
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_event, original_stream_config);
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
+  auto stream_config = rtc::MakeUnique<rtclog::StreamConfig>();
+  stream_config->local_ssrc = RandomSsrc();
+  stream_config->rtp_extensions.push_back(
+      RtpExtension(arbitrary_uri, RandomRtpExtensionId()));
+  stream_config->codecs.emplace_back("CODEC", 120, 3);
+
+  auto original_stream_config = *stream_config;
+
+  auto event =
+      rtc::MakeUnique<RtcEventVideoSendStreamConfig>(std::move(stream_config));
+  const int64_t timestamp_us = event->timestamp_us_;
+
+  ASSERT_TRUE(parsed_log_.ParseString(encoder_->Encode(*event)));
+  ASSERT_EQ(parsed_log_.GetNumberOfEvents(), 1u);
+  ASSERT_EQ(parsed_log_.GetEventType(0),
+            ParsedRtcEventLog::VIDEO_SENDER_CONFIG_EVENT);
+
+  auto parsed_event = parsed_log_.GetVideoSendConfig(0)[0];
+  EXPECT_EQ(parsed_log_.GetTimestamp(0), timestamp_us);
+  EXPECT_EQ(parsed_event, original_stream_config);
+}
+
+INSTANTIATE_TEST_CASE_P(RandomSeeds,
+                        RtcEventLogEncoderTest,
+                        ::testing::Values(1, 2, 3, 4, 5));
+
+}  // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_probe_result_failure.h b/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
index 76d8643..90ef4de 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
+++ b/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
@@ -15,10 +15,11 @@
 
 namespace webrtc {
 
-enum ProbeFailureReason {
-  kInvalidSendReceiveInterval,
+enum class ProbeFailureReason {
+  kInvalidSendReceiveInterval = 0,
   kInvalidSendReceiveRatio,
-  kTimeout
+  kTimeout,
+  kLast
 };
 
 class RtcEventProbeResultFailure final : public RtcEvent {
diff --git a/logging/rtc_event_log/rtc_event_log.cc b/logging/rtc_event_log/rtc_event_log.cc
index 5cb398d..bc9f143 100644
--- a/logging/rtc_event_log/rtc_event_log.cc
+++ b/logging/rtc_event_log/rtc_event_log.cc
@@ -219,6 +219,8 @@
       return rtclog::DelayBasedBweUpdate::BWE_UNDERUSING;
     case BandwidthUsage::kBwOverusing:
       return rtclog::DelayBasedBweUpdate::BWE_OVERUSING;
+    case BandwidthUsage::kLast:
+      RTC_NOTREACHED();
   }
   RTC_NOTREACHED();
   return rtclog::DelayBasedBweUpdate::BWE_NORMAL;
@@ -227,12 +229,14 @@
 rtclog::BweProbeResult::ResultType ConvertProbeResultType(
     ProbeFailureReason failure_reason) {
   switch (failure_reason) {
-    case kInvalidSendReceiveInterval:
+    case ProbeFailureReason::kInvalidSendReceiveInterval:
       return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL;
-    case kInvalidSendReceiveRatio:
+    case ProbeFailureReason::kInvalidSendReceiveRatio:
       return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO;
-    case kTimeout:
+    case ProbeFailureReason::kTimeout:
       return rtclog::BweProbeResult::TIMEOUT;
+    case ProbeFailureReason::kLast:
+      RTC_NOTREACHED();
   }
   RTC_NOTREACHED();
   return rtclog::BweProbeResult::SUCCESS;
diff --git a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
index dc4c496..c6fa129 100644
--- a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
+++ b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
@@ -132,7 +132,7 @@
       webrtc::test::RtpPacket packet;
       webrtc::PacketDirection direction;
       parsed_stream.GetRtpHeader(i, &direction, packet.data, &packet.length,
-                                 &packet.original_length);
+                                 &packet.original_length, nullptr);
       if (packet.original_length > packet.length)
         header_only = true;
       packet.time_ms = parsed_stream.GetTimestamp(i) / 1000;
diff --git a/logging/rtc_event_log/rtc_event_log2text.cc b/logging/rtc_event_log/rtc_event_log2text.cc
index 7eca099..af38964 100644
--- a/logging/rtc_event_log/rtc_event_log2text.cc
+++ b/logging/rtc_event_log/rtc_event_log2text.cc
@@ -431,7 +431,7 @@
           webrtc::PacketDirection direction;
           webrtc::RtpHeaderExtensionMap* extension_map =
               parsed_stream.GetRtpHeader(i, &direction, header, &header_length,
-                                         &total_length);
+                                         &total_length, nullptr);
 
           if (extension_map == nullptr)
             extension_map = &default_map;
@@ -728,7 +728,8 @@
           if (probe_result.failure_reason) {
             std::cout << parsed_stream.GetTimestamp(i) << "\tPROBE_SUCCESS("
                       << probe_result.id << ")"
-                      << "\tfailure_reason=" << *probe_result.failure_reason
+                      << "\tfailure_reason="
+                      << static_cast<int>(*probe_result.failure_reason)
                       << std::endl;
           } else {
             std::cout << parsed_stream.GetTimestamp(i) << "\tPROBE_SUCCESS("
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index cb4fd80..ca9ae39 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -280,7 +280,8 @@
     PacketDirection* incoming,
     uint8_t* header,
     size_t* header_length,
-    size_t* total_length) const {
+    size_t* total_length,
+    int* probe_cluster_id) const {
   RTC_CHECK_LT(index, GetNumberOfEvents());
   const rtclog::Event& event = events_[index];
   RTC_CHECK(event.has_type());
@@ -317,6 +318,14 @@
       return it->second;
     }
   }
+  if (probe_cluster_id != nullptr) {
+    if (rtp_packet.has_probe_cluster_id()) {
+      *probe_cluster_id = rtp_packet.probe_cluster_id();
+      RTC_CHECK_NE(*probe_cluster_id, PacedPacketInfo::kNotAProbe);
+    } else {
+      *probe_cluster_id = PacedPacketInfo::kNotAProbe;
+    }
+  }
   return nullptr;
 }
 
@@ -627,14 +636,15 @@
     res.bitrate_bps = rtc::Optional<uint64_t>(pr_event.bitrate_bps());
   } else if (pr_event.result() ==
              rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL) {
-    res.failure_reason =
-        rtc::Optional<ProbeFailureReason>(kInvalidSendReceiveInterval);
+    res.failure_reason = rtc::Optional<ProbeFailureReason>(
+        ProbeFailureReason::kInvalidSendReceiveInterval);
   } else if (pr_event.result() ==
              rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO) {
-    res.failure_reason =
-        rtc::Optional<ProbeFailureReason>(kInvalidSendReceiveRatio);
+    res.failure_reason = rtc::Optional<ProbeFailureReason>(
+        ProbeFailureReason::kInvalidSendReceiveRatio);
   } else if (pr_event.result() == rtclog::BweProbeResult::TIMEOUT) {
-    res.failure_reason = rtc::Optional<ProbeFailureReason>(kTimeout);
+    res.failure_reason =
+        rtc::Optional<ProbeFailureReason>(ProbeFailureReason::kTimeout);
   } else {
     RTC_NOTREACHED();
   }
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index 9f87c99..4980959 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -112,7 +112,8 @@
                                               PacketDirection* incoming,
                                               uint8_t* header,
                                               size_t* header_length,
-                                              size_t* total_length) const;
+                                              size_t* total_length,
+                                              int* probe_cluster_id) const;
 
   // Reads packet, direction and packet length from the RTCP event at |index|,
   // and stores the values in the corresponding output parameters.
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index 99e3e7e..629afbc 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -36,13 +36,6 @@
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
 
-// Files generated at build-time by the protobuf compiler.
-#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
-#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h"
-#else
-#include "logging/rtc_event_log/rtc_event_log.pb.h"
-#endif
-
 namespace webrtc {
 
 namespace {
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index ed9cab1..ff744cb 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -50,12 +50,14 @@
 rtclog::BweProbeResult::ResultType GetProbeResultType(
     ProbeFailureReason failure_reason) {
   switch (failure_reason) {
-    case kInvalidSendReceiveInterval:
+    case ProbeFailureReason::kInvalidSendReceiveInterval:
       return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL;
-    case kInvalidSendReceiveRatio:
+    case ProbeFailureReason::kInvalidSendReceiveRatio:
       return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO;
-    case kTimeout:
+    case ProbeFailureReason::kTimeout:
       return rtclog::BweProbeResult::TIMEOUT;
+    case ProbeFailureReason::kLast:
+      RTC_NOTREACHED();
   }
   RTC_NOTREACHED();
   return rtclog::BweProbeResult::SUCCESS;
@@ -373,7 +375,7 @@
   uint8_t parsed_header[1500];
   size_t parsed_header_size, parsed_total_size;
   parsed_log.GetRtpHeader(index, &parsed_direction, parsed_header,
-                          &parsed_header_size, &parsed_total_size);
+                          &parsed_header_size, &parsed_total_size, nullptr);
   EXPECT_EQ(kIncomingPacket, parsed_direction);
   EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size),
               testing::ElementsAreArray(parsed_header, parsed_header_size));
@@ -403,7 +405,7 @@
   uint8_t parsed_header[1500];
   size_t parsed_header_size, parsed_total_size;
   parsed_log.GetRtpHeader(index, &parsed_direction, parsed_header,
-                          &parsed_header_size, &parsed_total_size);
+                          &parsed_header_size, &parsed_total_size, nullptr);
   EXPECT_EQ(kOutgoingPacket, parsed_direction);
   EXPECT_THAT(testing::make_tuple(expected_packet.data(), header_size),
               testing::ElementsAreArray(parsed_header, parsed_header_size));
diff --git a/logging/rtc_event_log/rtc_stream_config.cc b/logging/rtc_event_log/rtc_stream_config.cc
index d54f6e0..b43c6dd 100644
--- a/logging/rtc_event_log/rtc_stream_config.cc
+++ b/logging/rtc_event_log/rtc_stream_config.cc
@@ -17,6 +17,13 @@
 
 StreamConfig::~StreamConfig() {}
 
+bool StreamConfig::operator==(const StreamConfig& other) const {
+  return local_ssrc == other.local_ssrc && remote_ssrc == other.remote_ssrc &&
+         rtx_ssrc == other.rtx_ssrc && rsid == other.rsid &&
+         remb == other.remb && rtcp_mode == other.rtcp_mode &&
+         rtp_extensions == other.rtp_extensions && codecs == other.codecs;
+}
+
 StreamConfig::Codec::Codec(const std::string& payload_name,
                            int payload_type,
                            int rtx_payload_type)
@@ -24,6 +31,11 @@
           payload_type(payload_type),
           rtx_payload_type(rtx_payload_type) {}
 
+bool StreamConfig::Codec::operator==(const Codec& other) const {
+  return payload_name == other.payload_name &&
+         payload_type == other.payload_type &&
+         rtx_payload_type == other.rtx_payload_type;
+}
 
 }  // namespace rtclog
 }  // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_stream_config.h b/logging/rtc_event_log/rtc_stream_config.h
index bbba251..e43ee7e 100644
--- a/logging/rtc_event_log/rtc_stream_config.h
+++ b/logging/rtc_event_log/rtc_stream_config.h
@@ -24,6 +24,8 @@
   StreamConfig();
   ~StreamConfig();
 
+  bool operator==(const StreamConfig& other) const;
+
   uint32_t local_ssrc = 0;
   uint32_t remote_ssrc = 0;
   uint32_t rtx_ssrc = 0;
@@ -39,6 +41,8 @@
           int payload_type,
           int rtx_payload_type);
 
+    bool operator==(const Codec& other) const;
+
     std::string payload_name;
     int payload_type;
     int rtx_payload_type;