Add version and UTC time fields to RTC event log.

Bug: webrtc:8111
Change-Id: I843e1f8e50e4d4faf74819e0104aeb4fb869b834
Reviewed-on: https://webrtc-review.googlesource.com/c/110721
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25658}
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
index beb711c..6ce750f 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
@@ -22,7 +22,8 @@
  public:
   virtual ~RtcEventLogEncoder() = default;
 
-  virtual std::string EncodeLogStart(int64_t timestamp_us) = 0;
+  virtual std::string EncodeLogStart(int64_t timestamp_us,
+                                     int64_t utc_time_us) = 0;
   virtual std::string EncodeLogEnd(int64_t timestamp_us) = 0;
 
   virtual std::string EncodeBatch(
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
index c60b211..29636ed 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -222,7 +222,8 @@
 
 }  // namespace
 
-std::string RtcEventLogEncoderLegacy::EncodeLogStart(int64_t timestamp_us) {
+std::string RtcEventLogEncoderLegacy::EncodeLogStart(int64_t timestamp_us,
+                                                     int64_t utc_time_us) {
   rtclog::Event rtclog_event;
   rtclog_event.set_timestamp_us(timestamp_us);
   rtclog_event.set_type(rtclog::Event::LOG_START);
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
index fd109f4..3105dc1 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
@@ -50,7 +50,8 @@
  public:
   ~RtcEventLogEncoderLegacy() override = default;
 
-  std::string EncodeLogStart(int64_t timestamp_us) override;
+  std::string EncodeLogStart(int64_t timestamp_us,
+                             int64_t utc_time_us) override;
   std::string EncodeLogEnd(int64_t timestamp_us) override;
 
   std::string EncodeBatch(
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
index b8cb747..a5cd177 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
@@ -615,10 +615,13 @@
 }
 }  // namespace
 
-std::string RtcEventLogEncoderNewFormat::EncodeLogStart(int64_t timestamp_us) {
+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();
 }
 
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
index d9a3f0a..7dfa490 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
@@ -56,7 +56,8 @@
       std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
       std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) override;
 
-  std::string EncodeLogStart(int64_t timestamp_us) override;
+  std::string EncodeLogStart(int64_t timestamp_us,
+                             int64_t utc_time_us) override;
   std::string EncodeLogEnd(int64_t timestamp_us) override;
 
  private:
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
index b29237e..856bec6 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -47,10 +47,12 @@
   RtcEventLogEncoderTest()
       : seed_(std::get<0>(GetParam())),
         prng_(seed_),
-        gen_(seed_ * 880001UL),
         new_encoding_(std::get<1>(GetParam())),
         event_count_(std::get<2>(GetParam())),
-        force_repeated_fields_(std::get<3>(GetParam())) {
+        force_repeated_fields_(std::get<3>(GetParam())),
+        gen_(seed_ * 880001UL),
+        verifier_(new_encoding_ ? RtcEventLog::EncodingType::NewFormat
+                                : RtcEventLog::EncodingType::Legacy) {
     if (new_encoding_)
       encoder_ = absl::make_unique<RtcEventLogEncoderNewFormat>();
     else
@@ -70,8 +72,9 @@
       const RtpHeaderExtensionMap& extension_map);
 
   template <typename ParsedType>
-  const std::vector<ParsedType>& GetRtpPacketsBySsrc(
-      const ParsedRtcEventLogNew* parsed_log);
+  const std::vector<ParsedType>* GetRtpPacketsBySsrc(
+      const ParsedRtcEventLogNew* parsed_log,
+      uint32_t ssrc);
 
   template <typename EventType, typename ParsedType>
   void TestRtpPackets();
@@ -81,10 +84,11 @@
   ParsedRtcEventLogNew parsed_log_;
   const uint64_t seed_;
   Random prng_;
-  test::EventGenerator gen_;
   const bool new_encoding_;
   const size_t event_count_;
   const bool force_repeated_fields_;
+  test::EventGenerator gen_;
+  test::EventVerifier verifier_;
 };
 
 void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
@@ -102,7 +106,8 @@
 
   ASSERT_EQ(ana_configs.size(), events.size());
   for (size_t i = 0; i < events.size(); ++i) {
-    test::VerifyLoggedAudioNetworkAdaptationEvent(*events[i], ana_configs[i]);
+    verifier_.VerifyLoggedAudioNetworkAdaptationEvent(*events[i],
+                                                      ana_configs[i]);
   }
 }
 
@@ -121,44 +126,31 @@
 }
 
 template <>
-const std::vector<ParsedRtcEventLogNew::LoggedRtpStreamIncoming>&
+const std::vector<LoggedRtpPacketIncoming>*
 RtcEventLogEncoderTest::GetRtpPacketsBySsrc(
-    const ParsedRtcEventLogNew* parsed_log) {
-  return parsed_log->incoming_rtp_packets_by_ssrc();
+    const ParsedRtcEventLogNew* parsed_log,
+    uint32_t ssrc) {
+  const auto& incoming_streams = parsed_log->incoming_rtp_packets_by_ssrc();
+  for (const auto& stream : incoming_streams) {
+    if (stream.ssrc == ssrc) {
+      return &stream.incoming_packets;
+    }
+  }
+  return nullptr;
 }
 
 template <>
-const std::vector<ParsedRtcEventLogNew::LoggedRtpStreamOutgoing>&
+const std::vector<LoggedRtpPacketOutgoing>*
 RtcEventLogEncoderTest::GetRtpPacketsBySsrc(
-    const ParsedRtcEventLogNew* parsed_log) {
-  return parsed_log->outgoing_rtp_packets_by_ssrc();
-}
-
-template <typename EventType, typename ParsedType>
-void CompareRtpPacketSequences(
-    const std::vector<std::unique_ptr<EventType>>& original_events,
-    const ParsedType& parsed_events);
-
-template <>
-void CompareRtpPacketSequences(
-    const std::vector<std::unique_ptr<RtcEventRtpPacketIncoming>>& original,
-    const ParsedRtcEventLogNew::LoggedRtpStreamIncoming& parsed) {
-  ASSERT_EQ(parsed.incoming_packets.size(), original.size());
-  for (size_t i = 0; i < original.size(); ++i) {
-    test::VerifyLoggedRtpPacketIncoming(*original[i],
-                                        parsed.incoming_packets[i]);
+    const ParsedRtcEventLogNew* parsed_log,
+    uint32_t ssrc) {
+  const auto& outgoing_streams = parsed_log->outgoing_rtp_packets_by_ssrc();
+  for (const auto& stream : outgoing_streams) {
+    if (stream.ssrc == ssrc) {
+      return &stream.outgoing_packets;
+    }
   }
-}
-
-template <>
-void CompareRtpPacketSequences(
-    const std::vector<std::unique_ptr<RtcEventRtpPacketOutgoing>>& original,
-    const ParsedRtcEventLogNew::LoggedRtpStreamOutgoing& parsed) {
-  ASSERT_EQ(parsed.outgoing_packets.size(), original.size());
-  for (size_t i = 0; i < original.size(); ++i) {
-    test::VerifyLoggedRtpPacketOutgoing(*original[i],
-                                        parsed.outgoing_packets[i]);
-  }
+  return nullptr;
 }
 
 template <typename EventType, typename ParsedType>
@@ -193,20 +185,19 @@
   std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
   ASSERT_TRUE(parsed_log_.ParseString(encoded));
 
-  // Expect as many distinct SSRCs to be parsed, as were simulated.
-  const std::vector<ParsedType>& parsed_rtp_packets =
-      GetRtpPacketsBySsrc<ParsedType>(&parsed_log_);
-  ASSERT_EQ(parsed_rtp_packets.size(), events_by_ssrc.size());
-
   // For each SSRC, make sure the RTP packets associated with it to have been
   // correctly encoded and parsed.
   for (auto it = events_by_ssrc.begin(); it != events_by_ssrc.end(); ++it) {
     const uint32_t ssrc = it->first;
-    auto parsed = std::find_if(
-        parsed_rtp_packets.begin(), parsed_rtp_packets.end(),
-        [ssrc](const ParsedType& packet) { return packet.ssrc == ssrc; });
-    ASSERT_NE(parsed, parsed_rtp_packets.end());
-    CompareRtpPacketSequences(it->second, *parsed);
+    const auto& original_packets = it->second;
+    const std::vector<ParsedType>* parsed_rtp_packets =
+        GetRtpPacketsBySsrc<ParsedType>(&parsed_log_, ssrc);
+    ASSERT_NE(parsed_rtp_packets, nullptr);
+    ASSERT_EQ(original_packets.size(), parsed_rtp_packets->size());
+    for (size_t i = 0; i < original_packets.size(); ++i) {
+      verifier_.VerifyLoggedRtpPacket<EventType, ParsedType>(
+          *original_packets[i], (*parsed_rtp_packets)[i]);
+    }
   }
 }
 
@@ -224,7 +215,7 @@
 
   ASSERT_EQ(alr_state_events.size(), event_count_);
   for (size_t i = 0; i < event_count_; ++i) {
-    test::VerifyLoggedAlrStateEvent(*events[i], alr_state_events[i]);
+    verifier_.VerifyLoggedAlrStateEvent(*events[i], alr_state_events[i]);
   }
 }
 
@@ -394,8 +385,8 @@
     ASSERT_EQ(original_playout_events.size(), parsed_playout_events.size());
 
     for (size_t i = 0; i < original_playout_events.size(); ++i) {
-      test::VerifyLoggedAudioPlayoutEvent(*original_playout_events[i],
-                                          parsed_playout_events[i]);
+      verifier_.VerifyLoggedAudioPlayoutEvent(*original_playout_events[i],
+                                              parsed_playout_events[i]);
     }
   }
 }
@@ -413,7 +404,7 @@
   const auto& audio_recv_configs = parsed_log_.audio_recv_configs();
 
   ASSERT_EQ(audio_recv_configs.size(), 1u);
-  test::VerifyLoggedAudioRecvConfig(*event, audio_recv_configs[0]);
+  verifier_.VerifyLoggedAudioRecvConfig(*event, audio_recv_configs[0]);
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -429,7 +420,7 @@
   const auto& audio_send_configs = parsed_log_.audio_send_configs();
 
   ASSERT_EQ(audio_send_configs.size(), 1u);
-  test::VerifyLoggedAudioSendConfig(*event, audio_send_configs[0]);
+  verifier_.VerifyLoggedAudioSendConfig(*event, audio_send_configs[0]);
 }
 
 TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
@@ -449,7 +440,7 @@
   ASSERT_EQ(bwe_delay_updates.size(), event_count_);
 
   for (size_t i = 0; i < event_count_; ++i) {
-    test::VerifyLoggedBweDelayBasedUpdate(*events[i], bwe_delay_updates[i]);
+    verifier_.VerifyLoggedBweDelayBasedUpdate(*events[i], bwe_delay_updates[i]);
   }
 }
 
@@ -469,7 +460,7 @@
   ASSERT_EQ(bwe_loss_updates.size(), event_count_);
 
   for (size_t i = 0; i < event_count_; ++i) {
-    test::VerifyLoggedBweLossBasedUpdate(*events[i], bwe_loss_updates[i]);
+    verifier_.VerifyLoggedBweLossBasedUpdate(*events[i], bwe_loss_updates[i]);
   }
 }
 
@@ -485,8 +476,8 @@
       parsed_log_.ice_candidate_pair_configs();
 
   ASSERT_EQ(ice_candidate_pair_configs.size(), 1u);
-  test::VerifyLoggedIceCandidatePairConfig(*event,
-                                           ice_candidate_pair_configs[0]);
+  verifier_.VerifyLoggedIceCandidatePairConfig(*event,
+                                               ice_candidate_pair_configs[0]);
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -500,23 +491,23 @@
       parsed_log_.ice_candidate_pair_events();
 
   ASSERT_EQ(ice_candidate_pair_events.size(), 1u);
-  test::VerifyLoggedIceCandidatePairEvent(*event, ice_candidate_pair_events[0]);
+  verifier_.VerifyLoggedIceCandidatePairEvent(*event,
+                                              ice_candidate_pair_events[0]);
 }
 
-// TODO(eladalon/terelius): Test with multiple events in the batch, or prevent
-// it from happening.
 TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
   const int64_t timestamp_us = rtc::TimeMicros();
+  const int64_t utc_time_us = rtc::TimeUTCMicros();
 
-  ASSERT_TRUE(parsed_log_.ParseString(encoder_->EncodeLogStart(timestamp_us)));
+  ASSERT_TRUE(parsed_log_.ParseString(
+      encoder_->EncodeLogStart(timestamp_us, utc_time_us)));
   const auto& start_log_events = parsed_log_.start_log_events();
 
   ASSERT_EQ(start_log_events.size(), 1u);
-  test::VerifyLoggedStartEvent(timestamp_us, start_log_events[0]);
+  verifier_.VerifyLoggedStartEvent(timestamp_us, utc_time_us,
+                                   start_log_events[0]);
 }
 
-// TODO(eladalon/terelius): Test with multiple events in the batch, or prevent
-// it from happening.
 TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
   const int64_t timestamp_us = rtc::TimeMicros();
 
@@ -524,7 +515,7 @@
   const auto& stop_log_events = parsed_log_.stop_log_events();
 
   ASSERT_EQ(stop_log_events.size(), 1u);
-  test::VerifyLoggedStopEvent(timestamp_us, stop_log_events[0]);
+  verifier_.VerifyLoggedStopEvent(timestamp_us, stop_log_events[0]);
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -539,7 +530,7 @@
       parsed_log_.bwe_probe_cluster_created_events();
 
   ASSERT_EQ(bwe_probe_cluster_created_events.size(), 1u);
-  test::VerifyLoggedBweProbeClusterCreatedEvent(
+  verifier_.VerifyLoggedBweProbeClusterCreatedEvent(
       *event, bwe_probe_cluster_created_events[0]);
 }
 
@@ -554,7 +545,8 @@
   const auto& bwe_probe_failure_events = parsed_log_.bwe_probe_failure_events();
 
   ASSERT_EQ(bwe_probe_failure_events.size(), 1u);
-  test::VerifyLoggedBweProbeFailureEvent(*event, bwe_probe_failure_events[0]);
+  verifier_.VerifyLoggedBweProbeFailureEvent(*event,
+                                             bwe_probe_failure_events[0]);
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -568,7 +560,8 @@
   const auto& bwe_probe_success_events = parsed_log_.bwe_probe_success_events();
 
   ASSERT_EQ(bwe_probe_success_events.size(), 1u);
-  test::VerifyLoggedBweProbeSuccessEvent(*event, bwe_probe_success_events[0]);
+  verifier_.VerifyLoggedBweProbeSuccessEvent(*event,
+                                             bwe_probe_success_events[0]);
 }
 
 TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
@@ -593,7 +586,8 @@
   ASSERT_EQ(incoming_rtcp_packets.size(), event_count_);
 
   for (size_t i = 0; i < event_count_; ++i) {
-    test::VerifyLoggedRtcpPacketIncoming(*events[i], incoming_rtcp_packets[i]);
+    verifier_.VerifyLoggedRtcpPacketIncoming(*events[i],
+                                             incoming_rtcp_packets[i]);
   }
 }
 
@@ -613,18 +607,17 @@
   ASSERT_EQ(outgoing_rtcp_packets.size(), event_count_);
 
   for (size_t i = 0; i < event_count_; ++i) {
-    test::VerifyLoggedRtcpPacketOutgoing(*events[i], outgoing_rtcp_packets[i]);
+    verifier_.VerifyLoggedRtcpPacketOutgoing(*events[i],
+                                             outgoing_rtcp_packets[i]);
   }
 }
 
 TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
-  TestRtpPackets<RtcEventRtpPacketIncoming,
-                 ParsedRtcEventLogNew::LoggedRtpStreamIncoming>();
+  TestRtpPackets<RtcEventRtpPacketIncoming, LoggedRtpPacketIncoming>();
 }
 
 TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
-  TestRtpPackets<RtcEventRtpPacketOutgoing,
-                 ParsedRtcEventLogNew::LoggedRtpStreamOutgoing>();
+  TestRtpPackets<RtcEventRtpPacketOutgoing, LoggedRtpPacketOutgoing>();
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -640,7 +633,7 @@
   const auto& video_recv_configs = parsed_log_.video_recv_configs();
 
   ASSERT_EQ(video_recv_configs.size(), 1u);
-  test::VerifyLoggedVideoRecvConfig(*event, video_recv_configs[0]);
+  verifier_.VerifyLoggedVideoRecvConfig(*event, video_recv_configs[0]);
 }
 
 // TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -656,7 +649,7 @@
   const auto& video_send_configs = parsed_log_.video_send_configs();
 
   ASSERT_EQ(video_send_configs.size(), 1u);
-  test::VerifyLoggedVideoSendConfig(*event, video_send_configs[0]);
+  verifier_.VerifyLoggedVideoSendConfig(*event, video_send_configs[0]);
 }
 
 INSTANTIATE_TEST_CASE_P(
diff --git a/logging/rtc_event_log/rtc_event_log2.proto b/logging/rtc_event_log/rtc_event_log2.proto
index 4e0e104..adaefd6 100644
--- a/logging/rtc_event_log/rtc_event_log2.proto
+++ b/logging/rtc_event_log/rtc_event_log2.proto
@@ -230,6 +230,12 @@
 message BeginLogEvent {
   // required
   optional int64 timestamp_ms = 1;
+
+  // required
+  optional uint32 version = 2;
+
+  // required
+  optional int64 utc_time_ms = 3;
 }
 
 message EndLogEvent {
diff --git a/logging/rtc_event_log/rtc_event_log_impl.cc b/logging/rtc_event_log/rtc_event_log_impl.cc
index 2954467..c022a3d 100644
--- a/logging/rtc_event_log/rtc_event_log_impl.cc
+++ b/logging/rtc_event_log/rtc_event_log_impl.cc
@@ -173,20 +173,19 @@
     return false;
   }
 
-  // TODO(terelius): The mapping between log timestamps and UTC should be stored
-  // in the event_log START event.
   const int64_t timestamp_us = rtc::TimeMicros();
   const int64_t utc_time_us = rtc::TimeUTCMicros();
   RTC_LOG(LS_INFO) << "Starting WebRTC event log. (Timestamp, UTC) = "
                    << "(" << timestamp_us << ", " << utc_time_us << ").";
 
   // Binding to |this| is safe because |this| outlives the |task_queue_|.
-  auto start = [this, timestamp_us](std::unique_ptr<RtcEventLogOutput> output) {
+  auto start = [this, timestamp_us,
+                utc_time_us](std::unique_ptr<RtcEventLogOutput> output) {
     RTC_DCHECK_RUN_ON(task_queue_.get());
     RTC_DCHECK(output->IsActive());
     event_output_ = std::move(output);
     num_config_events_written_ = 0;
-    WriteToOutput(event_encoder_->EncodeLogStart(timestamp_us));
+    WriteToOutput(event_encoder_->EncodeLogStart(timestamp_us, utc_time_us));
     LogEventsFromMemoryToOutput();
   };
 
diff --git a/logging/rtc_event_log/rtc_event_log_parser_new.cc b/logging/rtc_event_log/rtc_event_log_parser_new.cc
index 9fce840..0107722 100644
--- a/logging/rtc_event_log/rtc_event_log_parser_new.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser_new.cc
@@ -1943,7 +1943,11 @@
 void ParsedRtcEventLogNew::StoreStartEvent(
     const rtclog2::BeginLogEvent& proto) {
   RTC_CHECK(proto.has_timestamp_ms());
-  LoggedStartEvent start_event(proto.timestamp_ms() * 1000);
+  RTC_CHECK(proto.has_version());
+  RTC_CHECK(proto.has_utc_time_ms());
+  RTC_CHECK_EQ(proto.version(), 2);
+  LoggedStartEvent start_event(proto.timestamp_ms() * 1000,
+                               proto.utc_time_ms());
 
   start_log_events_.push_back(start_event);
 }
diff --git a/logging/rtc_event_log/rtc_event_log_parser_new.h b/logging/rtc_event_log/rtc_event_log_parser_new.h
index 7eb2237..50e3b99 100644
--- a/logging/rtc_event_log/rtc_event_log_parser_new.h
+++ b/logging/rtc_event_log/rtc_event_log_parser_new.h
@@ -369,12 +369,16 @@
 
 struct LoggedStartEvent {
   explicit LoggedStartEvent(int64_t timestamp_us)
-      : timestamp_us(timestamp_us) {}
+      : LoggedStartEvent(timestamp_us, timestamp_us / 1000) {}
+
+  LoggedStartEvent(int64_t timestamp_us, int64_t utc_start_time_ms)
+      : timestamp_us(timestamp_us), utc_start_time_ms(utc_start_time_ms) {}
 
   int64_t log_time_us() const { return timestamp_us; }
   int64_t log_time_ms() const { return timestamp_us / 1000; }
 
   int64_t timestamp_us;
+  int64_t utc_start_time_ms;
 };
 
 struct LoggedStopEvent {
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index bd136bb..f7b7898 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -107,9 +107,10 @@
   RtcEventLogSession()
       : seed_(std::get<0>(GetParam())),
         prng_(seed_),
-        gen_(seed_ * 880001UL),
         output_period_ms_(std::get<1>(GetParam())),
-        encoding_type_(std::get<2>(GetParam())) {
+        encoding_type_(std::get<2>(GetParam())),
+        gen_(seed_ * 880001UL),
+        verifier_(encoding_type_) {
     clock_.SetTimeMicros(prng_.Rand<uint32_t>());
     // Find the name of the current test, in order to use it as a temporary
     // filename.
@@ -168,13 +169,15 @@
   std::vector<std::unique_ptr<RtcEventRtcpPacketOutgoing>> outgoing_rtcp_list_;
 
   int64_t start_time_us_;
+  int64_t utc_start_time_us_;
   int64_t stop_time_us_;
 
   const uint64_t seed_;
   Random prng_;
-  test::EventGenerator gen_;
   const int64_t output_period_ms_;
   const RtcEventLog::EncodingType encoding_type_;
+  test::EventGenerator gen_;
+  test::EventVerifier verifier_;
   rtc::ScopedFakeClock clock_;
   std::string temp_filename_;
 };
@@ -308,6 +311,7 @@
           absl::make_unique<RtcEventLogOutputFile>(temp_filename_, 10000000),
           output_period_ms_);
       start_time_us_ = rtc::TimeMicros();
+      utc_start_time_us_ = rtc::TimeUTCMicros();
     }
 
     clock_.AdvanceTimeMicros(prng_.Rand(20) * 1000);
@@ -467,17 +471,18 @@
   // Start and stop events.
   auto& parsed_start_log_events = parsed_log.start_log_events();
   ASSERT_EQ(parsed_start_log_events.size(), static_cast<size_t>(1));
-  test::VerifyLoggedStartEvent(start_time_us_, parsed_start_log_events[0]);
+  verifier_.VerifyLoggedStartEvent(start_time_us_, utc_start_time_us_,
+                                   parsed_start_log_events[0]);
 
   auto& parsed_stop_log_events = parsed_log.stop_log_events();
   ASSERT_EQ(parsed_stop_log_events.size(), static_cast<size_t>(1));
-  test::VerifyLoggedStopEvent(stop_time_us_, parsed_stop_log_events[0]);
+  verifier_.VerifyLoggedStopEvent(stop_time_us_, parsed_stop_log_events[0]);
 
   auto& parsed_alr_state_events = parsed_log.alr_state_events();
   ASSERT_EQ(parsed_alr_state_events.size(), alr_state_list_.size());
   for (size_t i = 0; i < parsed_alr_state_events.size(); i++) {
-    test::VerifyLoggedAlrStateEvent(*alr_state_list_[i],
-                                    parsed_alr_state_events[i]);
+    verifier_.VerifyLoggedAlrStateEvent(*alr_state_list_[i],
+                                        parsed_alr_state_events[i]);
   }
 
   const auto& parsed_audio_playout_map = parsed_log.audio_playout_events();
@@ -488,8 +493,8 @@
     const auto& audio_playout_stream = audio_playout_map_[ssrc];
     ASSERT_EQ(parsed_audio_playout_stream.size(), audio_playout_stream.size());
     for (size_t i = 0; i < parsed_audio_playout_map.size(); i++) {
-      test::VerifyLoggedAudioPlayoutEvent(*audio_playout_stream[i],
-                                          parsed_audio_playout_stream[i]);
+      verifier_.VerifyLoggedAudioPlayoutEvent(*audio_playout_stream[i],
+                                              parsed_audio_playout_stream[i]);
     }
   }
 
@@ -498,22 +503,22 @@
   ASSERT_EQ(parsed_audio_network_adaptation_events.size(),
             ana_configs_list_.size());
   for (size_t i = 0; i < parsed_audio_network_adaptation_events.size(); i++) {
-    test::VerifyLoggedAudioNetworkAdaptationEvent(
+    verifier_.VerifyLoggedAudioNetworkAdaptationEvent(
         *ana_configs_list_[i], parsed_audio_network_adaptation_events[i]);
   }
 
   auto& parsed_bwe_delay_updates = parsed_log.bwe_delay_updates();
   ASSERT_EQ(parsed_bwe_delay_updates.size(), bwe_delay_list_.size());
   for (size_t i = 0; i < parsed_bwe_delay_updates.size(); i++) {
-    test::VerifyLoggedBweDelayBasedUpdate(*bwe_delay_list_[i],
-                                          parsed_bwe_delay_updates[i]);
+    verifier_.VerifyLoggedBweDelayBasedUpdate(*bwe_delay_list_[i],
+                                              parsed_bwe_delay_updates[i]);
   }
 
   auto& parsed_bwe_loss_updates = parsed_log.bwe_loss_updates();
   ASSERT_EQ(parsed_bwe_loss_updates.size(), bwe_loss_list_.size());
   for (size_t i = 0; i < parsed_bwe_loss_updates.size(); i++) {
-    test::VerifyLoggedBweLossBasedUpdate(*bwe_loss_list_[i],
-                                         parsed_bwe_loss_updates[i]);
+    verifier_.VerifyLoggedBweLossBasedUpdate(*bwe_loss_list_[i],
+                                             parsed_bwe_loss_updates[i]);
   }
 
   auto& parsed_bwe_probe_cluster_created_events =
@@ -521,29 +526,29 @@
   ASSERT_EQ(parsed_bwe_probe_cluster_created_events.size(),
             probe_creation_list_.size());
   for (size_t i = 0; i < parsed_bwe_probe_cluster_created_events.size(); i++) {
-    test::VerifyLoggedBweProbeClusterCreatedEvent(
+    verifier_.VerifyLoggedBweProbeClusterCreatedEvent(
         *probe_creation_list_[i], parsed_bwe_probe_cluster_created_events[i]);
   }
 
   auto& parsed_bwe_probe_failure_events = parsed_log.bwe_probe_failure_events();
   ASSERT_EQ(parsed_bwe_probe_failure_events.size(), probe_failure_list_.size());
   for (size_t i = 0; i < parsed_bwe_probe_failure_events.size(); i++) {
-    test::VerifyLoggedBweProbeFailureEvent(*probe_failure_list_[i],
-                                           parsed_bwe_probe_failure_events[i]);
+    verifier_.VerifyLoggedBweProbeFailureEvent(
+        *probe_failure_list_[i], parsed_bwe_probe_failure_events[i]);
   }
 
   auto& parsed_bwe_probe_success_events = parsed_log.bwe_probe_success_events();
   ASSERT_EQ(parsed_bwe_probe_success_events.size(), probe_success_list_.size());
   for (size_t i = 0; i < parsed_bwe_probe_success_events.size(); i++) {
-    test::VerifyLoggedBweProbeSuccessEvent(*probe_success_list_[i],
-                                           parsed_bwe_probe_success_events[i]);
+    verifier_.VerifyLoggedBweProbeSuccessEvent(
+        *probe_success_list_[i], parsed_bwe_probe_success_events[i]);
   }
 
   auto& parsed_ice_candidate_pair_configs =
       parsed_log.ice_candidate_pair_configs();
   ASSERT_EQ(parsed_ice_candidate_pair_configs.size(), ice_config_list_.size());
   for (size_t i = 0; i < parsed_ice_candidate_pair_configs.size(); i++) {
-    test::VerifyLoggedIceCandidatePairConfig(
+    verifier_.VerifyLoggedIceCandidatePairConfig(
         *ice_config_list_[i], parsed_ice_candidate_pair_configs[i]);
   }
 
@@ -552,7 +557,7 @@
   ASSERT_EQ(parsed_ice_candidate_pair_events.size(),
             parsed_ice_candidate_pair_events.size());
   for (size_t i = 0; i < parsed_ice_candidate_pair_events.size(); i++) {
-    test::VerifyLoggedIceCandidatePairEvent(
+    verifier_.VerifyLoggedIceCandidatePairEvent(
         *ice_event_list_[i], parsed_ice_candidate_pair_events[i]);
   }
 
@@ -566,7 +571,8 @@
     const auto& rtp_stream = incoming_rtp_map_[ssrc];
     ASSERT_EQ(parsed_rtp_stream.size(), rtp_stream.size());
     for (size_t i = 0; i < parsed_rtp_stream.size(); i++) {
-      test::VerifyLoggedRtpPacketIncoming(*rtp_stream[i], parsed_rtp_stream[i]);
+      verifier_.VerifyLoggedRtpPacketIncoming(*rtp_stream[i],
+                                              parsed_rtp_stream[i]);
     }
   }
 
@@ -580,46 +586,47 @@
     const auto& rtp_stream = outgoing_rtp_map_[ssrc];
     ASSERT_EQ(parsed_rtp_stream.size(), rtp_stream.size());
     for (size_t i = 0; i < parsed_rtp_stream.size(); i++) {
-      test::VerifyLoggedRtpPacketOutgoing(*rtp_stream[i], parsed_rtp_stream[i]);
+      verifier_.VerifyLoggedRtpPacketOutgoing(*rtp_stream[i],
+                                              parsed_rtp_stream[i]);
     }
   }
 
   auto& parsed_incoming_rtcp_packets = parsed_log.incoming_rtcp_packets();
   ASSERT_EQ(parsed_incoming_rtcp_packets.size(), incoming_rtcp_list_.size());
   for (size_t i = 0; i < parsed_incoming_rtcp_packets.size(); i++) {
-    test::VerifyLoggedRtcpPacketIncoming(*incoming_rtcp_list_[i],
-                                         parsed_incoming_rtcp_packets[i]);
+    verifier_.VerifyLoggedRtcpPacketIncoming(*incoming_rtcp_list_[i],
+                                             parsed_incoming_rtcp_packets[i]);
   }
 
   auto& parsed_outgoing_rtcp_packets = parsed_log.outgoing_rtcp_packets();
   ASSERT_EQ(parsed_outgoing_rtcp_packets.size(), outgoing_rtcp_list_.size());
   for (size_t i = 0; i < parsed_outgoing_rtcp_packets.size(); i++) {
-    test::VerifyLoggedRtcpPacketOutgoing(*outgoing_rtcp_list_[i],
-                                         parsed_outgoing_rtcp_packets[i]);
+    verifier_.VerifyLoggedRtcpPacketOutgoing(*outgoing_rtcp_list_[i],
+                                             parsed_outgoing_rtcp_packets[i]);
   }
   auto& parsed_audio_recv_configs = parsed_log.audio_recv_configs();
   ASSERT_EQ(parsed_audio_recv_configs.size(), audio_recv_config_list_.size());
   for (size_t i = 0; i < parsed_audio_recv_configs.size(); i++) {
-    test::VerifyLoggedAudioRecvConfig(*audio_recv_config_list_[i],
-                                      parsed_audio_recv_configs[i]);
+    verifier_.VerifyLoggedAudioRecvConfig(*audio_recv_config_list_[i],
+                                          parsed_audio_recv_configs[i]);
   }
   auto& parsed_audio_send_configs = parsed_log.audio_send_configs();
   ASSERT_EQ(parsed_audio_send_configs.size(), audio_send_config_list_.size());
   for (size_t i = 0; i < parsed_audio_send_configs.size(); i++) {
-    test::VerifyLoggedAudioSendConfig(*audio_send_config_list_[i],
-                                      parsed_audio_send_configs[i]);
+    verifier_.VerifyLoggedAudioSendConfig(*audio_send_config_list_[i],
+                                          parsed_audio_send_configs[i]);
   }
   auto& parsed_video_recv_configs = parsed_log.video_recv_configs();
   ASSERT_EQ(parsed_video_recv_configs.size(), video_recv_config_list_.size());
   for (size_t i = 0; i < parsed_video_recv_configs.size(); i++) {
-    test::VerifyLoggedVideoRecvConfig(*video_recv_config_list_[i],
-                                      parsed_video_recv_configs[i]);
+    verifier_.VerifyLoggedVideoRecvConfig(*video_recv_config_list_[i],
+                                          parsed_video_recv_configs[i]);
   }
   auto& parsed_video_send_configs = parsed_log.video_send_configs();
   ASSERT_EQ(parsed_video_send_configs.size(), video_send_config_list_.size());
   for (size_t i = 0; i < parsed_video_send_configs.size(); i++) {
-    test::VerifyLoggedVideoSendConfig(*video_send_config_list_[i],
-                                      parsed_video_send_configs[i]);
+    verifier_.VerifyLoggedVideoSendConfig(*video_send_config_list_[i],
+                                          parsed_video_send_configs[i]);
   }
 
   // Clean up temporary file - can be pretty slow.
@@ -690,8 +697,10 @@
 class RtcEventLogCircularBufferTest
     : public ::testing::TestWithParam<RtcEventLog::EncodingType> {
  public:
-  RtcEventLogCircularBufferTest() : encoding_type_(GetParam()) {}
+  RtcEventLogCircularBufferTest()
+      : encoding_type_(GetParam()), verifier_(encoding_type_) {}
   const RtcEventLog::EncodingType encoding_type_;
+  const test::EventVerifier verifier_;
 };
 
 TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
@@ -727,6 +736,7 @@
     fake_clock->AdvanceTimeMicros(10000);
   }
   int64_t start_time_us = rtc::TimeMicros();
+  int64_t utc_start_time_us = rtc::TimeUTCMicros();
   log_dumper->StartLogging(
       absl::make_unique<RtcEventLogOutputFile>(temp_filename, 10000000),
       RtcEventLog::kImmediateOutput);
@@ -740,11 +750,12 @@
 
   const auto& start_log_events = parsed_log.start_log_events();
   ASSERT_EQ(start_log_events.size(), 1u);
-  test::VerifyLoggedStartEvent(start_time_us, start_log_events[0]);
+  verifier_.VerifyLoggedStartEvent(start_time_us, utc_start_time_us,
+                                   start_log_events[0]);
 
   const auto& stop_log_events = parsed_log.stop_log_events();
   ASSERT_EQ(stop_log_events.size(), 1u);
-  test::VerifyLoggedStopEvent(stop_time_us, stop_log_events[0]);
+  verifier_.VerifyLoggedStopEvent(stop_time_us, stop_log_events[0]);
 
   const auto& probe_success_events = parsed_log.bwe_probe_success_events();
   // If the following fails, it probably means that kNumEvents isn't larger
@@ -765,7 +776,7 @@
   fake_clock->SetTimeMicros(first_timestamp_us);
   for (size_t i = 1; i < probe_success_events.size(); i++) {
     fake_clock->AdvanceTimeMicros(10000);
-    test::VerifyLoggedBweProbeSuccessEvent(
+    verifier_.VerifyLoggedBweProbeSuccessEvent(
         RtcEventProbeResultSuccess(first_id + i, first_bitrate_bps + i * 1000),
         probe_success_events[i]);
   }
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 215c986..a0c5d32 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -501,22 +501,23 @@
   return absl::make_unique<RtcEventVideoSendStreamConfig>(std::move(config));
 }
 
-void VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event,
-                               const LoggedAlrStateEvent& logged_event) {
+void EventVerifier::VerifyLoggedAlrStateEvent(
+    const RtcEventAlrState& original_event,
+    const LoggedAlrStateEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.in_alr(), logged_event.in_alr);
 }
 
-void VerifyLoggedAudioPlayoutEvent(
+void EventVerifier::VerifyLoggedAudioPlayoutEvent(
     const RtcEventAudioPlayout& original_event,
-    const LoggedAudioPlayoutEvent& logged_event) {
+    const LoggedAudioPlayoutEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.ssrc(), logged_event.ssrc);
 }
 
-void VerifyLoggedAudioNetworkAdaptationEvent(
+void EventVerifier::VerifyLoggedAudioNetworkAdaptationEvent(
     const RtcEventAudioNetworkAdaptation& original_event,
-    const LoggedAudioNetworkAdaptationEvent& logged_event) {
+    const LoggedAudioNetworkAdaptationEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   EXPECT_EQ(original_event.config().bitrate_bps,
@@ -541,26 +542,26 @@
   }
 }
 
-void VerifyLoggedBweDelayBasedUpdate(
+void EventVerifier::VerifyLoggedBweDelayBasedUpdate(
     const RtcEventBweUpdateDelayBased& original_event,
-    const LoggedBweDelayBasedUpdate& logged_event) {
+    const LoggedBweDelayBasedUpdate& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.bitrate_bps(), logged_event.bitrate_bps);
   EXPECT_EQ(original_event.detector_state(), logged_event.detector_state);
 }
 
-void VerifyLoggedBweLossBasedUpdate(
+void EventVerifier::VerifyLoggedBweLossBasedUpdate(
     const RtcEventBweUpdateLossBased& original_event,
-    const LoggedBweLossBasedUpdate& logged_event) {
+    const LoggedBweLossBasedUpdate& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.bitrate_bps(), logged_event.bitrate_bps);
   EXPECT_EQ(original_event.fraction_loss(), logged_event.fraction_lost);
   EXPECT_EQ(original_event.total_packets(), logged_event.expected_packets);
 }
 
-void VerifyLoggedBweProbeClusterCreatedEvent(
+void EventVerifier::VerifyLoggedBweProbeClusterCreatedEvent(
     const RtcEventProbeClusterCreated& original_event,
-    const LoggedBweProbeClusterCreatedEvent& logged_event) {
+    const LoggedBweProbeClusterCreatedEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.id(), logged_event.id);
   EXPECT_EQ(original_event.bitrate_bps(), logged_event.bitrate_bps);
@@ -568,25 +569,25 @@
   EXPECT_EQ(original_event.min_bytes(), logged_event.min_bytes);
 }
 
-void VerifyLoggedBweProbeFailureEvent(
+void EventVerifier::VerifyLoggedBweProbeFailureEvent(
     const RtcEventProbeResultFailure& original_event,
-    const LoggedBweProbeFailureEvent& logged_event) {
+    const LoggedBweProbeFailureEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.id(), logged_event.id);
   EXPECT_EQ(original_event.failure_reason(), logged_event.failure_reason);
 }
 
-void VerifyLoggedBweProbeSuccessEvent(
+void EventVerifier::VerifyLoggedBweProbeSuccessEvent(
     const RtcEventProbeResultSuccess& original_event,
-    const LoggedBweProbeSuccessEvent& logged_event) {
+    const LoggedBweProbeSuccessEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   EXPECT_EQ(original_event.id(), logged_event.id);
   EXPECT_EQ(original_event.bitrate_bps(), logged_event.bitrate_bps);
 }
 
-void VerifyLoggedIceCandidatePairConfig(
+void EventVerifier::VerifyLoggedIceCandidatePairConfig(
     const RtcEventIceCandidatePairConfig& original_event,
-    const LoggedIceCandidatePairConfig& logged_event) {
+    const LoggedIceCandidatePairConfig& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   EXPECT_EQ(original_event.type(), logged_event.type);
@@ -607,9 +608,9 @@
             logged_event.candidate_pair_protocol);
 }
 
-void VerifyLoggedIceCandidatePairEvent(
+void EventVerifier::VerifyLoggedIceCandidatePairEvent(
     const RtcEventIceCandidatePair& original_event,
-    const LoggedIceCandidatePairEvent& logged_event) {
+    const LoggedIceCandidatePairEvent& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   EXPECT_EQ(original_event.type(), logged_event.type);
@@ -677,9 +678,9 @@
   }
 }
 
-void VerifyLoggedRtpPacketIncoming(
+void EventVerifier::VerifyLoggedRtpPacketIncoming(
     const RtcEventRtpPacketIncoming& original_event,
-    const LoggedRtpPacketIncoming& logged_event) {
+    const LoggedRtpPacketIncoming& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   EXPECT_EQ(original_event.header().headers_size(),
@@ -695,9 +696,9 @@
   VerifyLoggedRtpHeader(original_event.header(), logged_event.rtp.header);
 }
 
-void VerifyLoggedRtpPacketOutgoing(
+void EventVerifier::VerifyLoggedRtpPacketOutgoing(
     const RtcEventRtpPacketOutgoing& original_event,
-    const LoggedRtpPacketOutgoing& logged_event) {
+    const LoggedRtpPacketOutgoing& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   EXPECT_EQ(original_event.header().headers_size(),
@@ -716,9 +717,9 @@
   VerifyLoggedRtpHeader(original_event.header(), logged_event.rtp.header);
 }
 
-void VerifyLoggedRtcpPacketIncoming(
+void EventVerifier::VerifyLoggedRtcpPacketIncoming(
     const RtcEventRtcpPacketIncoming& original_event,
-    const LoggedRtcpPacketIncoming& logged_event) {
+    const LoggedRtcpPacketIncoming& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   ASSERT_EQ(original_event.packet().size(), logged_event.rtcp.raw_data.size());
@@ -728,9 +729,9 @@
       0);
 }
 
-void VerifyLoggedRtcpPacketOutgoing(
+void EventVerifier::VerifyLoggedRtcpPacketOutgoing(
     const RtcEventRtcpPacketOutgoing& original_event,
-    const LoggedRtcpPacketOutgoing& logged_event) {
+    const LoggedRtcpPacketOutgoing& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
 
   ASSERT_EQ(original_event.packet().size(), logged_event.rtcp.raw_data.size());
@@ -740,13 +741,19 @@
       0);
 }
 
-void VerifyLoggedStartEvent(int64_t start_time_us,
-                            const LoggedStartEvent& logged_event) {
+void EventVerifier::VerifyLoggedStartEvent(
+    int64_t start_time_us,
+    int64_t utc_start_time_us,
+    const LoggedStartEvent& logged_event) const {
   EXPECT_EQ(start_time_us / 1000, logged_event.log_time_ms());
+  if (encoding_type_ == RtcEventLog::EncodingType::NewFormat) {
+    EXPECT_EQ(utc_start_time_us / 1000, logged_event.utc_start_time_ms);
+  }
 }
 
-void VerifyLoggedStopEvent(int64_t stop_time_us,
-                           const LoggedStopEvent& logged_event) {
+void EventVerifier::VerifyLoggedStopEvent(
+    int64_t stop_time_us,
+    const LoggedStopEvent& logged_event) const {
   EXPECT_EQ(stop_time_us / 1000, logged_event.log_time_ms());
 }
 
@@ -776,30 +783,30 @@
   EXPECT_EQ(recognized_extensions, original_config.rtp_extensions.size());
 }
 
-void VerifyLoggedAudioRecvConfig(
+void EventVerifier::VerifyLoggedAudioRecvConfig(
     const RtcEventAudioReceiveStreamConfig& original_event,
-    const LoggedAudioRecvConfig& logged_event) {
+    const LoggedAudioRecvConfig& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   VerifyLoggedStreamConfig(original_event.config(), logged_event.config);
 }
 
-void VerifyLoggedAudioSendConfig(
+void EventVerifier::VerifyLoggedAudioSendConfig(
     const RtcEventAudioSendStreamConfig& original_event,
-    const LoggedAudioSendConfig& logged_event) {
+    const LoggedAudioSendConfig& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   VerifyLoggedStreamConfig(original_event.config(), logged_event.config);
 }
 
-void VerifyLoggedVideoRecvConfig(
+void EventVerifier::VerifyLoggedVideoRecvConfig(
     const RtcEventVideoReceiveStreamConfig& original_event,
-    const LoggedVideoRecvConfig& logged_event) {
+    const LoggedVideoRecvConfig& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   VerifyLoggedStreamConfig(original_event.config(), logged_event.config);
 }
 
-void VerifyLoggedVideoSendConfig(
+void EventVerifier::VerifyLoggedVideoSendConfig(
     const RtcEventVideoSendStreamConfig& original_event,
-    const LoggedVideoSendConfig& logged_event) {
+    const LoggedVideoSendConfig& logged_event) const {
   EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
   // TODO(terelius): In the past, we allowed storing multiple RtcStreamConfigs
   // in the same RtcEventVideoSendStreamConfig. Look into whether we should drop
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index d25970c..81760b7 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -122,83 +122,111 @@
   Random prng_;
 };
 
-void VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event,
-                               const LoggedAlrStateEvent& logged_event);
+class EventVerifier {
+ public:
+  explicit EventVerifier(RtcEventLog::EncodingType encoding_type)
+      : encoding_type_(encoding_type) {}
 
-void VerifyLoggedAudioPlayoutEvent(const RtcEventAudioPlayout& original_event,
-                                   const LoggedAudioPlayoutEvent& logged_event);
+  void VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event,
+                                 const LoggedAlrStateEvent& logged_event) const;
 
-void VerifyLoggedAudioNetworkAdaptationEvent(
-    const RtcEventAudioNetworkAdaptation& original_event,
-    const LoggedAudioNetworkAdaptationEvent& logged_event);
+  void VerifyLoggedAudioPlayoutEvent(
+      const RtcEventAudioPlayout& original_event,
+      const LoggedAudioPlayoutEvent& logged_event) const;
 
-void VerifyLoggedBweDelayBasedUpdate(
-    const RtcEventBweUpdateDelayBased& original_event,
-    const LoggedBweDelayBasedUpdate& logged_event);
+  void VerifyLoggedAudioNetworkAdaptationEvent(
+      const RtcEventAudioNetworkAdaptation& original_event,
+      const LoggedAudioNetworkAdaptationEvent& logged_event) const;
 
-void VerifyLoggedBweLossBasedUpdate(
-    const RtcEventBweUpdateLossBased& original_event,
-    const LoggedBweLossBasedUpdate& logged_event);
+  void VerifyLoggedBweDelayBasedUpdate(
+      const RtcEventBweUpdateDelayBased& original_event,
+      const LoggedBweDelayBasedUpdate& logged_event) const;
 
-void VerifyLoggedBweProbeClusterCreatedEvent(
-    const RtcEventProbeClusterCreated& original_event,
-    const LoggedBweProbeClusterCreatedEvent& logged_event);
+  void VerifyLoggedBweLossBasedUpdate(
+      const RtcEventBweUpdateLossBased& original_event,
+      const LoggedBweLossBasedUpdate& logged_event) const;
 
-void VerifyLoggedBweProbeFailureEvent(
-    const RtcEventProbeResultFailure& original_event,
-    const LoggedBweProbeFailureEvent& logged_event);
+  void VerifyLoggedBweProbeClusterCreatedEvent(
+      const RtcEventProbeClusterCreated& original_event,
+      const LoggedBweProbeClusterCreatedEvent& logged_event) const;
 
-void VerifyLoggedBweProbeSuccessEvent(
-    const RtcEventProbeResultSuccess& original_event,
-    const LoggedBweProbeSuccessEvent& logged_event);
+  void VerifyLoggedBweProbeFailureEvent(
+      const RtcEventProbeResultFailure& original_event,
+      const LoggedBweProbeFailureEvent& logged_event) const;
 
-void VerifyLoggedIceCandidatePairConfig(
-    const RtcEventIceCandidatePairConfig& original_event,
-    const LoggedIceCandidatePairConfig& logged_event);
+  void VerifyLoggedBweProbeSuccessEvent(
+      const RtcEventProbeResultSuccess& original_event,
+      const LoggedBweProbeSuccessEvent& logged_event) const;
 
-void VerifyLoggedIceCandidatePairEvent(
-    const RtcEventIceCandidatePair& original_event,
-    const LoggedIceCandidatePairEvent& logged_event);
+  void VerifyLoggedIceCandidatePairConfig(
+      const RtcEventIceCandidatePairConfig& original_event,
+      const LoggedIceCandidatePairConfig& logged_event) const;
 
-void VerifyLoggedRtpPacketIncoming(
-    const RtcEventRtpPacketIncoming& original_event,
-    const LoggedRtpPacketIncoming& logged_event);
+  void VerifyLoggedIceCandidatePairEvent(
+      const RtcEventIceCandidatePair& original_event,
+      const LoggedIceCandidatePairEvent& logged_event) const;
 
-void VerifyLoggedRtpPacketOutgoing(
-    const RtcEventRtpPacketOutgoing& original_event,
-    const LoggedRtpPacketOutgoing& logged_event);
+  void VerifyLoggedRtpPacketIncoming(
+      const RtcEventRtpPacketIncoming& original_event,
+      const LoggedRtpPacketIncoming& logged_event) const;
 
-void VerifyLoggedRtcpPacketIncoming(
-    const RtcEventRtcpPacketIncoming& original_event,
-    const LoggedRtcpPacketIncoming& logged_event);
+  void VerifyLoggedRtpPacketOutgoing(
+      const RtcEventRtpPacketOutgoing& original_event,
+      const LoggedRtpPacketOutgoing& logged_event) const;
 
-void VerifyLoggedRtcpPacketOutgoing(
-    const RtcEventRtcpPacketOutgoing& original_event,
-    const LoggedRtcpPacketOutgoing& logged_event);
+  template <typename EventType, typename ParsedType>
+  void VerifyLoggedRtpPacket(const EventType& original_event,
+                             const ParsedType& logged_event) {
+    static_assert(sizeof(ParsedType) == 0,
+                  "You have to use one of the two defined template "
+                  "specializations of VerifyLoggedRtpPacket");
+  }
 
-void VerifyLoggedStartEvent(int64_t start_time_us,
-                            const LoggedStartEvent& logged_event);
-void VerifyLoggedStopEvent(int64_t stop_time_us,
-                           const LoggedStopEvent& logged_event);
+  template <>
+  void VerifyLoggedRtpPacket(const RtcEventRtpPacketIncoming& original_event,
+                             const LoggedRtpPacketIncoming& logged_event) {
+    VerifyLoggedRtpPacketIncoming(original_event, logged_event);
+  }
 
-void VerifyLoggedStreamConfig(const rtclog::StreamConfig& original_config,
-                              const rtclog::StreamConfig& logged_config);
+  template <>
+  void VerifyLoggedRtpPacket(const RtcEventRtpPacketOutgoing& original_event,
+                             const LoggedRtpPacketOutgoing& logged_event) {
+    VerifyLoggedRtpPacketOutgoing(original_event, logged_event);
+  }
 
-void VerifyLoggedAudioRecvConfig(
-    const RtcEventAudioReceiveStreamConfig& original_event,
-    const LoggedAudioRecvConfig& logged_event);
+  void VerifyLoggedRtcpPacketIncoming(
+      const RtcEventRtcpPacketIncoming& original_event,
+      const LoggedRtcpPacketIncoming& logged_event) const;
 
-void VerifyLoggedAudioSendConfig(
-    const RtcEventAudioSendStreamConfig& original_event,
-    const LoggedAudioSendConfig& logged_event);
+  void VerifyLoggedRtcpPacketOutgoing(
+      const RtcEventRtcpPacketOutgoing& original_event,
+      const LoggedRtcpPacketOutgoing& logged_event) const;
 
-void VerifyLoggedVideoRecvConfig(
-    const RtcEventVideoReceiveStreamConfig& original_event,
-    const LoggedVideoRecvConfig& logged_event);
+  void VerifyLoggedStartEvent(int64_t start_time_us,
+                              int64_t utc_start_time_us,
+                              const LoggedStartEvent& logged_event) const;
+  void VerifyLoggedStopEvent(int64_t stop_time_us,
+                             const LoggedStopEvent& logged_event) const;
 
-void VerifyLoggedVideoSendConfig(
-    const RtcEventVideoSendStreamConfig& original_event,
-    const LoggedVideoSendConfig& logged_event);
+  void VerifyLoggedAudioRecvConfig(
+      const RtcEventAudioReceiveStreamConfig& original_event,
+      const LoggedAudioRecvConfig& logged_event) const;
+
+  void VerifyLoggedAudioSendConfig(
+      const RtcEventAudioSendStreamConfig& original_event,
+      const LoggedAudioSendConfig& logged_event) const;
+
+  void VerifyLoggedVideoRecvConfig(
+      const RtcEventVideoReceiveStreamConfig& original_event,
+      const LoggedVideoRecvConfig& logged_event) const;
+
+  void VerifyLoggedVideoSendConfig(
+      const RtcEventVideoSendStreamConfig& original_event,
+      const LoggedVideoSendConfig& logged_event) const;
+
+ private:
+  RtcEventLog::EncodingType encoding_type_;
+};
 
 }  // namespace test
 }  // namespace webrtc