/* * Copyright (c) 2023 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_RTC_EVENT_PROCESSOR_ORDER_H_ #define LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_ORDER_H_ #include #include "absl/types/optional.h" #include "api/function_view.h" #include "logging/rtc_event_log/events/logged_rtp_rtcp.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" namespace webrtc { // The RTC event log only uses millisecond precision timestamps // and doesn't preserve order between events in different batches. // This is a heuristic to order events in a way that preserves // "typical" dependencies, e.g. we receive packets before we // send feedback about them, and RTP packets sent or received // during the same millisecond are in sequence number order. enum class TypeOrder { Start, // Connectivity and stream configurations before incoming packets StreamConfig, IceCondidateConfig, IceCandidateEvent, DtlsTransportState, DtlsWritable, RouteChange, // Incoming packets RtpIn, RtcpIn, GenericPacketIn, GenericAckIn, // BWE depends on incoming feedback (send side estimation) // or incoming media packets (receive side estimation). // Delay-based BWE depends on probe results. // Loss-based BWE depends on delay-based BWE. // Loss-based BWE may trigger new probes. BweRemoteEstimate, BweProbeFailure, BweProbeSuccess, BweDelayBased, BweLossBased, BweProbeCreated, // General processing events. No obvious order. AudioNetworkAdaptation, NetEqSetMinDelay, AudioPlayout, FrameDecoded, // Outgoing packets and feedback depends on BWE and might depend on // processing. RtpOut, RtcpOut, GenericPacketOut, // Alr is updated after a packet is sent. AlrState, Stop, }; template class TieBreaker { static_assert(sizeof(T) != sizeof(T), "Specialize TieBreaker to define an order for the event type."); }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::Start); static absl::optional transport_seq_num_accessor( const LoggedStartEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::Stop); static absl::optional transport_seq_num_accessor( const LoggedStopEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::StreamConfig); static absl::optional transport_seq_num_accessor( const LoggedAudioRecvConfig&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::StreamConfig); static absl::optional transport_seq_num_accessor( const LoggedAudioSendConfig&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::StreamConfig); static absl::optional transport_seq_num_accessor( const LoggedVideoRecvConfig&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::StreamConfig); static absl::optional transport_seq_num_accessor( const LoggedVideoSendConfig&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::IceCondidateConfig); static absl::optional transport_seq_num_accessor( const LoggedIceCandidatePairConfig&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::IceCandidateEvent); static absl::optional transport_seq_num_accessor( const LoggedIceCandidatePairEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::DtlsTransportState); static absl::optional transport_seq_num_accessor( const LoggedDtlsTransportState&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::DtlsWritable); static absl::optional transport_seq_num_accessor( const LoggedDtlsWritableState&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::RouteChange); static absl::optional transport_seq_num_accessor( const LoggedRouteChangeEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweRemoteEstimate); static absl::optional transport_seq_num_accessor( const LoggedRemoteEstimateEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweProbeFailure); static absl::optional transport_seq_num_accessor( const LoggedBweProbeFailureEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweProbeSuccess); static absl::optional transport_seq_num_accessor( const LoggedBweProbeSuccessEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweDelayBased); static absl::optional transport_seq_num_accessor( const LoggedBweDelayBasedUpdate&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweLossBased); static absl::optional transport_seq_num_accessor( const LoggedBweLossBasedUpdate&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::BweProbeCreated); static absl::optional transport_seq_num_accessor( const LoggedBweProbeClusterCreatedEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::AudioNetworkAdaptation); static absl::optional transport_seq_num_accessor( const LoggedAudioNetworkAdaptationEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::NetEqSetMinDelay); static absl::optional transport_seq_num_accessor( const LoggedNetEqSetMinimumDelayEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::AudioPlayout); static absl::optional transport_seq_num_accessor( const LoggedAudioPlayoutEvent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::FrameDecoded); static absl::optional transport_seq_num_accessor( const LoggedFrameDecoded&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::GenericPacketIn); static absl::optional transport_seq_num_accessor( const LoggedGenericPacketReceived&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::GenericAckIn); static absl::optional transport_seq_num_accessor( const LoggedGenericAckReceived&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::GenericPacketOut); static absl::optional transport_seq_num_accessor( const LoggedGenericPacketSent&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order(PacketDirection direction) { return static_cast(direction == PacketDirection::kIncomingPacket ? TypeOrder::RtpIn : TypeOrder::RtpOut); } static absl::optional transport_seq_num_accessor( const LoggedRtpPacket& p) { return p.header.extension.hasTransportSequenceNumber ? p.header.extension.transportSequenceNumber : absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order(PacketDirection direction) { return static_cast(direction == PacketDirection::kIncomingPacket ? TypeOrder::RtpIn : TypeOrder::RtpOut); } static absl::optional transport_seq_num_accessor( const LoggedPacketInfo& p) { return p.has_transport_seq_no ? p.transport_seq_no : absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::RtpIn); static absl::optional transport_seq_num_accessor( const LoggedRtpPacketIncoming& p) { return p.rtp.header.extension.hasTransportSequenceNumber ? p.rtp.header.extension.transportSequenceNumber : absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::RtpOut); static absl::optional transport_seq_num_accessor( const LoggedRtpPacketOutgoing& p) { return p.rtp.header.extension.hasTransportSequenceNumber ? p.rtp.header.extension.transportSequenceNumber : absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::RtcpIn); static absl::optional transport_seq_num_accessor( const LoggedRtcpPacketIncoming&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::RtcpOut); static absl::optional transport_seq_num_accessor( const LoggedRtcpPacketOutgoing&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order(PacketDirection direction) { return static_cast(direction == PacketDirection::kIncomingPacket ? TypeOrder::RtcpIn : TypeOrder::RtcpOut); } static absl::optional transport_seq_num_accessor( const LoggedRtcpPacketTransportFeedback&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order(PacketDirection direction) { return static_cast(direction == PacketDirection::kIncomingPacket ? TypeOrder::RtcpIn : TypeOrder::RtcpOut); } static absl::optional transport_seq_num_accessor( const LoggedRtcpPacketReceiverReport&) { return absl::optional(); } }; template <> class TieBreaker { public: static constexpr int type_order = static_cast(TypeOrder::AlrState); static absl::optional transport_seq_num_accessor( const LoggedAlrStateEvent&) { return absl::optional(); } }; } // namespace webrtc #endif // LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_ORDER_H_