Prepare for new event log parser.

Minor clean up of BUILD file.
Add explicit events for begin and end of log.
Add a helper function to populate timestamps.
Add a GroupKey method that will be used for grouping events by for example SSRC in additon to event type.

Bug: webrtc:11933
Change-Id: Ie3c5f5a5582c89805a0273f4b27978f47ed0fb4f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/234260
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35725}
diff --git a/api/rtc_event_log/rtc_event.h b/api/rtc_event_log/rtc_event.h
index 51db8f0..8697a25 100644
--- a/api/rtc_event_log/rtc_event.h
+++ b/api/rtc_event_log/rtc_event.h
@@ -27,7 +27,7 @@
   // of Type. This leaks the information of existing subclasses into the
   // superclass, but the *actual* information - rtclog::StreamConfig, etc. -
   // is kept separate.
-  enum class Type {
+  enum class Type : uint32_t {
     AlrStateEvent,
     RouteChangeEvent,
     RemoteEstimateEvent,
@@ -53,7 +53,9 @@
     GenericPacketSent,
     GenericPacketReceived,
     GenericAckReceived,
-    FrameDecoded
+    FrameDecoded,
+    BeginV3Log = 0x2501580,
+    EndV3Log = 0x2501581
   };
 
   RtcEvent();
@@ -63,6 +65,13 @@
 
   virtual bool IsConfigEvent() const = 0;
 
+  // Events are grouped by Type before being encoded.
+  // Optionally, `GetGroupKey` can be overloaded to group the
+  // events by a secondary key (in addition to the event type.)
+  // This can, in some cases, improve compression efficiency
+  // e.g. by grouping events by SSRC.
+  virtual uint32_t GetGroupKey() const { return 0; }
+
   int64_t timestamp_ms() const { return timestamp_us_ / 1000; }
   int64_t timestamp_us() const { return timestamp_us_; }
 
diff --git a/api/rtc_event_log/rtc_event_log.h b/api/rtc_event_log/rtc_event_log.h
index 86613dd..7b42cdc 100644
--- a/api/rtc_event_log/rtc_event_log.h
+++ b/api/rtc_event_log/rtc_event_log.h
@@ -29,7 +29,7 @@
 
   // TODO(eladalon):  Get rid of the legacy encoding and this enum once all
   // clients have migrated to the new format.
-  enum class EncodingType { Legacy, NewFormat };
+  enum class EncodingType { Legacy, NewFormat, ProtoFree };
 
   virtual ~RtcEventLog() = default;
 
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index eae92de..67c01fa 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -18,6 +18,7 @@
 group("logging") {
   deps = [
     ":rtc_event_audio",
+    ":rtc_event_begin_end",
     ":rtc_event_bwe",
     ":rtc_event_log_impl_encoder",
     ":rtc_event_pacing",
@@ -48,6 +49,7 @@
     ":rtc_event_number_encodings",
     "../api:array_view",
     "../api/rtc_event_log",
+    "../api/units:timestamp",
     "../rtc_base:bitstream_reader",
     "../rtc_base:checks",
     "../rtc_base:logging",
@@ -78,7 +80,7 @@
   ]
 
   deps = [
-    "../api:scoped_refptr",
+    ":rtc_event_field",
     "../api/rtc_event_log",
     "../api/units:timestamp",
   ]
@@ -99,7 +101,6 @@
 
   deps = [
     ":rtc_stream_config",
-    "../api:scoped_refptr",
     "../api/rtc_event_log",
     "../api/units:timestamp",
     "../modules/audio_coding:audio_network_adaptor_config",
@@ -108,6 +109,22 @@
   absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
 }
 
+rtc_library("rtc_event_begin_end") {
+  sources = [
+    "rtc_event_log/events/rtc_event_begin_log.cc",
+    "rtc_event_log/events/rtc_event_begin_log.h",
+    "rtc_event_log/events/rtc_event_end_log.cc",
+    "rtc_event_log/events/rtc_event_end_log.h",
+  ]
+  deps = [
+    ":rtc_event_field",
+    "../api:array_view",
+    "../api/rtc_event_log",
+    "../api/units:timestamp",
+  ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
+}
+
 rtc_library("rtc_event_bwe") {
   sources = [
     "rtc_event_log/events/rtc_event_bwe_update_delay_based.cc",
@@ -127,7 +144,6 @@
 
   deps = [
     "../api:network_state_predictor_api",
-    "../api:scoped_refptr",
     "../api/rtc_event_log",
     "../api/units:data_rate",
     "../api/units:timestamp",
@@ -190,7 +206,6 @@
 
   deps = [
     "../api:array_view",
-    "../api:scoped_refptr",
     "../api/rtc_event_log",
     "../modules/rtp_rtcp:rtp_rtcp_format",
     "../rtc_base:checks",
@@ -209,7 +224,6 @@
 
   deps = [
     ":rtc_stream_config",
-    "../api:scoped_refptr",
     "../api/rtc_event_log",
     "../api/units:timestamp",
     "../rtc_base:checks",
@@ -275,6 +289,7 @@
     deps += [
       ":ice_log",
       ":rtc_event_audio",
+      ":rtc_event_begin_end",
       ":rtc_event_bwe",
       ":rtc_event_frame_events",
       ":rtc_event_generic_packet_events",
@@ -374,6 +389,7 @@
     deps = [
       ":ice_log",
       ":rtc_event_audio",
+      ":rtc_event_begin_end",
       ":rtc_event_bwe",
       ":rtc_event_frame_events",
       ":rtc_event_generic_packet_events",
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 ff72163..add42ad 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
@@ -363,6 +363,12 @@
           static_cast<const RtcEventVideoSendStreamConfig&>(event);
       return EncodeVideoSendStreamConfig(rtc_event);
     }
+    case RtcEvent::Type::BeginV3Log:
+    case RtcEvent::Type::EndV3Log:
+      // These special events are written as part of starting
+      // and stopping the log, and only as part of version 3 of the format.
+      RTC_DCHECK_NOTREACHED();
+      break;
     case RtcEvent::Type::RouteChangeEvent:
     case RtcEvent::Type::RemoteEstimateEvent:
     case RtcEvent::Type::GenericPacketReceived:
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 ce9f813..d88f124 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
@@ -880,6 +880,12 @@
           frames_decoded[rtc_event->ssrc()].emplace_back(rtc_event);
           break;
         }
+        case RtcEvent::Type::BeginV3Log:
+        case RtcEvent::Type::EndV3Log:
+          // These special events are written as part of starting
+          // and stopping the log, and only as part of version 3 of the format.
+          RTC_DCHECK_NOTREACHED();
+          break;
       }
     }
 
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 8eddc8f..bd898a1 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
@@ -61,6 +61,10 @@
       case RtcEventLog::EncodingType::NewFormat:
         encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
         break;
+      case RtcEventLog::EncodingType::ProtoFree:
+        // TODO(terelius): Enable test once the format has been wired up.
+        RTC_CHECK_NOTREACHED();
+        break;
     }
     encoded_ =
         encoder_->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
@@ -1285,6 +1289,10 @@
       case RtcEventLog::EncodingType::NewFormat:
         encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
         break;
+      case RtcEventLog::EncodingType::ProtoFree:
+        // TODO(terelius): Enable test once the format has been wired up.
+        RTC_CHECK_NOTREACHED();
+        break;
     }
     encoded_ =
         encoder_->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
diff --git a/logging/rtc_event_log/events/rtc_event_begin_log.cc b/logging/rtc_event_log/events/rtc_event_begin_log.cc
new file mode 100644
index 0000000..15db8f5
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_begin_log.cc
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (c) 2021 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/events/rtc_event_begin_log.h"
+
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+constexpr RtcEvent::Type RtcEventBeginLog::kType;
+constexpr EventParameters RtcEventBeginLog::event_params_;
+constexpr FieldParameters RtcEventBeginLog::utc_start_time_params_;
+
+RtcEventBeginLog::RtcEventBeginLog(Timestamp timestamp,
+                                   Timestamp utc_start_time)
+    : RtcEvent(timestamp.us()), utc_start_time_ms_(utc_start_time.ms()) {}
+
+RtcEventBeginLog::RtcEventBeginLog(const RtcEventBeginLog& other)
+    : RtcEvent(other.timestamp_us_) {}
+
+RtcEventBeginLog::~RtcEventBeginLog() = default;
+
+std::string RtcEventBeginLog::Encode(rtc::ArrayView<const RtcEvent*> batch) {
+  EventEncoder encoder(event_params_, batch);
+
+  encoder.EncodeField(
+      utc_start_time_params_,
+      ExtractRtcEventMember(batch, &RtcEventBeginLog::utc_start_time_ms_));
+
+  return encoder.AsString();
+}
+
+RtcEventLogParseStatus RtcEventBeginLog::Parse(
+    absl::string_view encoded_bytes,
+    bool batched,
+    std::vector<LoggedStartEvent>& output) {
+  EventParser parser;
+  auto status = parser.Initialize(encoded_bytes, batched);
+  if (!status.ok())
+    return status;
+
+  rtc::ArrayView<LoggedStartEvent> output_batch =
+      ExtendLoggedBatch(output, parser.NumEventsInBatch());
+
+  constexpr FieldParameters timestamp_params{
+      "timestamp_ms", FieldParameters::kTimestampField, FieldType::kVarInt, 64};
+  RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+      parser.ParseNumericField(timestamp_params);
+  if (!result.ok())
+    return result.status();
+  PopulateRtcEventTimestamp(result.value(), &LoggedStartEvent::timestamp,
+                            output_batch);
+
+  result = parser.ParseNumericField(utc_start_time_params_);
+  if (!result.ok())
+    return result.status();
+  PopulateRtcEventTimestamp(result.value(), &LoggedStartEvent::utc_start_time,
+                            output_batch);
+
+  return RtcEventLogParseStatus::Success();
+}
+
+}  // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_begin_log.h b/logging/rtc_event_log/events/rtc_event_begin_log.h
new file mode 100644
index 0000000..8dc47b5
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_begin_log.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2021 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_EVENTS_RTC_EVENT_BEGIN_LOG_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BEGIN_LOG_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+namespace webrtc {
+
+struct LoggedStartEvent {
+  LoggedStartEvent() = default;
+
+  explicit LoggedStartEvent(Timestamp timestamp)
+      : LoggedStartEvent(timestamp, timestamp) {}
+
+  LoggedStartEvent(Timestamp timestamp, Timestamp utc_start_time)
+      : timestamp(timestamp), utc_start_time(utc_start_time) {}
+
+  int64_t log_time_us() const { return timestamp.us(); }
+  int64_t log_time_ms() const { return timestamp.ms(); }
+
+  Timestamp utc_time() const { return utc_start_time; }
+
+  Timestamp timestamp = Timestamp::PlusInfinity();
+  Timestamp utc_start_time = Timestamp::PlusInfinity();
+};
+
+class RtcEventBeginLog final : public RtcEvent {
+ public:
+  static constexpr Type kType = Type::BeginV3Log;
+
+  RtcEventBeginLog(Timestamp timestamp, Timestamp utc_start_time);
+  ~RtcEventBeginLog() override;
+
+  Type GetType() const override { return kType; }
+  bool IsConfigEvent() const override { return false; }
+
+  static std::string Encode(rtc::ArrayView<const RtcEvent*> batch);
+
+  static RtcEventLogParseStatus Parse(absl::string_view encoded_bytes,
+                                      bool batched,
+                                      std::vector<LoggedStartEvent>& output);
+
+ private:
+  RtcEventBeginLog(const RtcEventBeginLog& other);
+
+  int64_t utc_start_time_ms_;
+
+  static constexpr EventParameters event_params_{"BeginLog",
+                                                 RtcEventBeginLog::kType};
+  static constexpr FieldParameters utc_start_time_params_{
+      "utc_start_time_ms", /*id=*/1, FieldType::kVarInt, /*width=*/64};
+};
+
+}  // namespace webrtc
+#endif  // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BEGIN_LOG_H_
diff --git a/logging/rtc_event_log/events/rtc_event_end_log.cc b/logging/rtc_event_log/events/rtc_event_end_log.cc
new file mode 100644
index 0000000..fa9930a
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_end_log.cc
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2021 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/events/rtc_event_end_log.h"
+
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+constexpr RtcEvent::Type RtcEventEndLog::kType;
+constexpr EventParameters RtcEventEndLog::event_params_;
+
+RtcEventEndLog::RtcEventEndLog(Timestamp timestamp)
+    : RtcEvent(timestamp.us()) {}
+
+RtcEventEndLog::RtcEventEndLog(const RtcEventEndLog& other)
+    : RtcEvent(other.timestamp_us_) {}
+
+RtcEventEndLog::~RtcEventEndLog() = default;
+
+std::string RtcEventEndLog::Encode(rtc::ArrayView<const RtcEvent*> batch) {
+  EventEncoder encoder(event_params_, batch);
+  return encoder.AsString();
+}
+
+RtcEventLogParseStatus RtcEventEndLog::Parse(
+    absl::string_view encoded_bytes,
+    bool batched,
+    std::vector<LoggedStopEvent>& output) {
+  EventParser parser;
+  auto status = parser.Initialize(encoded_bytes, batched);
+  if (!status.ok())
+    return status;
+
+  rtc::ArrayView<LoggedStopEvent> output_batch =
+      ExtendLoggedBatch(output, parser.NumEventsInBatch());
+
+  constexpr FieldParameters timestamp_params{
+      "timestamp_ms", FieldParameters::kTimestampField, FieldType::kVarInt, 64};
+  RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+      parser.ParseNumericField(timestamp_params);
+  if (!result.ok())
+    return result.status();
+  PopulateRtcEventTimestamp(result.value(), &LoggedStopEvent::timestamp,
+                            output_batch);
+
+  return RtcEventLogParseStatus::Success();
+}
+
+}  // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_end_log.h b/logging/rtc_event_log/events/rtc_event_end_log.h
new file mode 100644
index 0000000..ed7770f
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_end_log.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2021 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_EVENTS_RTC_EVENT_END_LOG_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_END_LOG_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+namespace webrtc {
+
+struct LoggedStopEvent {
+  LoggedStopEvent() = default;
+
+  explicit LoggedStopEvent(Timestamp timestamp) : timestamp(timestamp) {}
+
+  int64_t log_time_us() const { return timestamp.us(); }
+  int64_t log_time_ms() const { return timestamp.ms(); }
+
+  Timestamp timestamp = Timestamp::PlusInfinity();
+};
+
+class RtcEventEndLog final : public RtcEvent {
+ public:
+  static constexpr Type kType = Type::EndV3Log;
+
+  explicit RtcEventEndLog(Timestamp timestamp);
+  ~RtcEventEndLog() override;
+
+  Type GetType() const override { return kType; }
+  bool IsConfigEvent() const override { return false; }
+
+  static std::string Encode(rtc::ArrayView<const RtcEvent*> batch);
+
+  static RtcEventLogParseStatus Parse(absl::string_view encoded_bytes,
+                                      bool batched,
+                                      std::vector<LoggedStopEvent>& output);
+
+ private:
+  RtcEventEndLog(const RtcEventEndLog& other);
+
+  static constexpr EventParameters event_params_{"EndLog",
+                                                 RtcEventEndLog::kType};
+};
+
+}  // namespace webrtc
+#endif  // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_END_LOG_H_
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h
index f1af5db..398f63d 100644
--- a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h
@@ -36,6 +36,7 @@
   }
 
   bool ok() const { return error_.empty(); }
+  ABSL_DEPRECATED("Use ok() instead") operator bool() const { return ok(); }
 
   std::string message() const { return error_; }
 
@@ -50,15 +51,17 @@
 template <typename T>
 class RtcEventLogParseStatusOr {
  public:
-  explicit RtcEventLogParseStatusOr(RtcEventLogParseStatus status)
+  RtcEventLogParseStatusOr(RtcEventLogParseStatus status)  // NOLINT
       : status_(status), value_() {}
-  explicit RtcEventLogParseStatusOr(const T& value)
+  RtcEventLogParseStatusOr(const T& value)  // NOLINT
       : status_(), value_(value) {}
 
   bool ok() const { return status_.ok(); }
 
   std::string message() const { return status_.message(); }
 
+  RtcEventLogParseStatus status() const { return status_; }
+
   const T& value() const {
     RTC_DCHECK(ok());
     return value_;
diff --git a/logging/rtc_event_log/events/rtc_event_field_extraction.h b/logging/rtc_event_log/events/rtc_event_field_extraction.h
index 8cd020f..0e0fffe 100644
--- a/logging/rtc_event_log/events/rtc_event_field_extraction.h
+++ b/logging/rtc_event_log/events/rtc_event_field_extraction.h
@@ -17,6 +17,7 @@
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
 #include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
 #include "rtc_base/logging.h"
 
@@ -181,6 +182,29 @@
   }
 }
 
+template <typename E>
+void PopulateRtcEventTimestamp(const rtc::ArrayView<uint64_t>& values,
+                               Timestamp E::*timestamp,
+                               rtc::ArrayView<E> output) {
+  size_t batch_size = values.size();
+  RTC_CHECK_EQ(batch_size, output.size());
+  for (size_t i = 0; i < batch_size; ++i) {
+    output[i].*timestamp =
+        Timestamp::Millis(DecodeFromUnsignedToType<int64_t>(values[i]));
+  }
+}
+
+template <typename E>
+rtc::ArrayView<E> ExtendLoggedBatch(std::vector<E>& output,
+                                    size_t new_elements) {
+  size_t old_size = output.size();
+  output.insert(output.end(), old_size + new_elements, E());
+  rtc::ArrayView<E> output_batch = output;
+  output_batch.subview(old_size);
+  RTC_DCHECK_EQ(output_batch.size(), new_elements);
+  return output_batch;
+}
+
 }  // namespace webrtc
 
 #endif  // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_EXTRACTION_H_
diff --git a/logging/rtc_event_log/logged_events.h b/logging/rtc_event_log/logged_events.h
index 5bce658..9268940 100644
--- a/logging/rtc_event_log/logged_events.h
+++ b/logging/rtc_event_log/logged_events.h
@@ -239,31 +239,6 @@
   rtcp::Bye bye;
 };
 
-struct LoggedStartEvent {
-  explicit LoggedStartEvent(Timestamp timestamp)
-      : LoggedStartEvent(timestamp, timestamp) {}
-
-  LoggedStartEvent(Timestamp timestamp, Timestamp utc_start_time)
-      : timestamp(timestamp), utc_start_time(utc_start_time) {}
-
-  int64_t log_time_us() const { return timestamp.us(); }
-  int64_t log_time_ms() const { return timestamp.ms(); }
-
-  Timestamp utc_time() const { return utc_start_time; }
-
-  Timestamp timestamp;
-  Timestamp utc_start_time;
-};
-
-struct LoggedStopEvent {
-  explicit LoggedStopEvent(Timestamp timestamp) : timestamp(timestamp) {}
-
-  int64_t log_time_us() const { return timestamp.us(); }
-  int64_t log_time_ms() const { return timestamp.ms(); }
-
-  Timestamp timestamp;
-};
-
 struct InferredRouteChangeEvent {
   int64_t log_time_ms() const { return log_time.ms(); }
   int64_t log_time_us() const { return log_time.us(); }
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index d4c8409..bbd8df2 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -15,7 +15,6 @@
 #include <map>
 #include <set>
 #include <string>
-#include <utility>  // pair
 #include <vector>
 
 #include "absl/base/attributes.h"
@@ -27,10 +26,12 @@
 #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_begin_log.h"
 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
 #include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
 #include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/events/rtc_event_end_log.h"
 #include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
 #include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
 #include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
@@ -240,48 +241,11 @@
     kDontParse,
     kAttemptWebrtcDefaultConfig
   };
-  class ParseStatus {
-   public:
-    static ParseStatus Success() { return ParseStatus(); }
-    static ParseStatus Error(std::string error, std::string file, int line) {
-      return ParseStatus(error, file, line);
-    }
 
-    bool ok() const { return error_.empty() && file_.empty() && line_ == 0; }
-    std::string message() const {
-      return error_ + " failed at " + file_ + " line " + std::to_string(line_);
-    }
-
-    ABSL_DEPRECATED("Use ok() instead") operator bool() const { return ok(); }
-
-   private:
-    ParseStatus() : error_(), file_(), line_(0) {}
-    ParseStatus(std::string error, std::string file, int line)
-        : error_(error), file_(file), line_(line) {}
-    std::string error_;
-    std::string file_;
-    int line_;
-  };
+  using ParseStatus = RtcEventLogParseStatus;
 
   template <typename T>
-  class ParseStatusOr {
-   public:
-    ParseStatusOr(const ParseStatus& error)  // NOLINT
-        : status_(error), value_() {}
-    ParseStatusOr(const T& value)  // NOLINT
-        : status_(ParseStatus::Success()), value_(value) {}
-    bool ok() const { return status_.ok(); }
-    const T& value() const& {
-      RTC_DCHECK(status_.ok());
-      return value_;
-    }
-    std::string message() const { return status_.message(); }
-    const ParseStatus& status() const { return status_; }
-
-   private:
-    ParseStatus status_;
-    T value_;
-  };
+  using ParseStatusOr = RtcEventLogParseStatusOr<T>;
 
   struct LoggedRtpStreamIncoming {
     LoggedRtpStreamIncoming();