/* * Copyright (c) 2012 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 MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_ #define MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_ #include #include #include #include #include "absl/types/optional.h" #include "api/array_view.h" #include "api/sequence_checker.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "modules/rtp_rtcp/include/report_block_data.h" #include "modules/rtp_rtcp/include/rtcp_statistics.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "modules/rtp_rtcp/source/rtcp_nack_stats.h" #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h" #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h" #include "rtc_base/containers/flat_map.h" #include "rtc_base/synchronization/mutex.h" #include "rtc_base/system/no_unique_address.h" #include "rtc_base/thread_annotations.h" #include "system_wrappers/include/ntp_time.h" namespace webrtc { class ModuleRtpRtcpImpl2; class VideoBitrateAllocationObserver; namespace rtcp { class CommonHeader; class ReportBlock; class Rrtr; class TargetBitrate; class TmmbItem; } // namespace rtcp class RTCPReceiver final { public: class ModuleRtpRtcp { public: virtual void SetTmmbn(std::vector bounding_set) = 0; virtual void OnRequestSendReport() = 0; virtual void OnReceivedNack( const std::vector& nack_sequence_numbers) = 0; virtual void OnReceivedRtcpReportBlocks( rtc::ArrayView report_blocks) = 0; protected: virtual ~ModuleRtpRtcp() = default; }; // Standardized stats derived from the non-sender RTT. class NonSenderRttStats { public: NonSenderRttStats() = default; NonSenderRttStats(const NonSenderRttStats&) = default; NonSenderRttStats& operator=(const NonSenderRttStats&) = default; ~NonSenderRttStats() = default; void Update(TimeDelta non_sender_rtt_seconds) { round_trip_time_ = non_sender_rtt_seconds; total_round_trip_time_ += non_sender_rtt_seconds; round_trip_time_measurements_++; } void Invalidate() { round_trip_time_.reset(); } // https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptime absl::optional round_trip_time() const { return round_trip_time_; } // https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-totalroundtriptime TimeDelta total_round_trip_time() const { return total_round_trip_time_; } // https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptimemeasurements int round_trip_time_measurements() const { return round_trip_time_measurements_; } private: absl::optional round_trip_time_; TimeDelta total_round_trip_time_ = TimeDelta::Zero(); int round_trip_time_measurements_ = 0; }; RTCPReceiver(const RtpRtcpInterface::Configuration& config, ModuleRtpRtcp* owner); RTCPReceiver(const RtpRtcpInterface::Configuration& config, ModuleRtpRtcpImpl2* owner); ~RTCPReceiver(); void IncomingPacket(rtc::ArrayView packet); int64_t LastReceivedReportBlockMs() const; void set_local_media_ssrc(uint32_t ssrc); uint32_t local_media_ssrc() const; void SetRemoteSSRC(uint32_t ssrc); uint32_t RemoteSSRC() const; bool receiver_only() const { return receiver_only_; } // Returns stats based on the received RTCP Sender Reports. absl::optional GetSenderReportStats() const; std::vector ConsumeReceivedXrReferenceTimeInfo(); // Get received sender packet and octet counts void RemoteRTCPSenderInfo(uint32_t* packet_count, uint32_t* octet_count, int64_t* ntp_timestamp_ms, int64_t* remote_ntp_timestamp_ms) const; absl::optional AverageRtt() const; absl::optional LastRtt() const; // Returns non-sender RTT metrics for the remote SSRC. NonSenderRttStats GetNonSenderRTT() const; void SetNonSenderRttMeasurement(bool enabled); absl::optional GetAndResetXrRrRtt(); // Called once per second on the worker thread to do rtt calculations. // Returns an optional rtt value if one is available. absl::optional OnPeriodicRttUpdate(Timestamp newer_than, bool sending); // A snapshot of Report Blocks with additional data of interest to statistics. // Within this list, the source SSRC is unique and ReportBlockData represents // the latest Report Block that was received for that SSRC. std::vector GetLatestReportBlockData() const; // Returns true if we haven't received an RTCP RR for several RTCP // intervals, but only triggers true once. bool RtcpRrTimeout(); // Returns true if we haven't received an RTCP RR telling the receive side // has not received RTP packets for too long, i.e. extended highest sequence // number hasn't increased for several RTCP intervals. The function only // returns true once until a new RR is received. bool RtcpRrSequenceNumberTimeout(); std::vector TmmbrReceived(); // Return true if new bandwidth should be set. bool UpdateTmmbrTimers(); std::vector BoundingSet(bool* tmmbr_owner); // Set new bandwidth and notify remote clients about it. void NotifyTmmbrUpdated(); private: #if RTC_DCHECK_IS_ON class CustomSequenceChecker : public SequenceChecker { public: explicit CustomSequenceChecker(bool disable_checks) : disable_checks_(disable_checks) {} bool IsCurrent() const { if (disable_checks_) return true; return SequenceChecker::IsCurrent(); } private: const bool disable_checks_; }; #else class CustomSequenceChecker : public SequenceChecker { public: explicit CustomSequenceChecker(bool) {} }; #endif // A lightweight inlined set of local SSRCs. class RegisteredSsrcs { public: static constexpr size_t kMediaSsrcIndex = 0; static constexpr size_t kMaxSsrcs = 3; // Initializes the set of registered local SSRCS by extracting them from the // provided `config`. The `disable_sequence_checker` flag is a workaround // to be able to use a sequence checker without breaking downstream // code that currently doesn't follow the same threading rules as webrtc. RegisteredSsrcs(bool disable_sequence_checker, const RtpRtcpInterface::Configuration& config); // Indicates if `ssrc` is in the set of registered local SSRCs. bool contains(uint32_t ssrc) const; uint32_t media_ssrc() const; void set_media_ssrc(uint32_t ssrc); private: RTC_NO_UNIQUE_ADDRESS CustomSequenceChecker packet_sequence_checker_; absl::InlinedVector ssrcs_ RTC_GUARDED_BY(packet_sequence_checker_); }; struct PacketInformation; // Structure for handing TMMBR and TMMBN rtcp messages (RFC5104, // section 3.5.4). struct TmmbrInformation { struct TimedTmmbrItem { rtcp::TmmbItem tmmbr_item; Timestamp last_updated = Timestamp::Zero(); }; Timestamp last_time_received = Timestamp::Zero(); bool ready_for_delete = false; std::vector tmmbn; std::map tmmbr; }; // Structure for storing received RRTR RTCP messages (RFC3611, section 4.4). struct RrtrInformation { RrtrInformation(uint32_t ssrc, uint32_t received_remote_mid_ntp_time, uint32_t local_receive_mid_ntp_time) : ssrc(ssrc), received_remote_mid_ntp_time(received_remote_mid_ntp_time), local_receive_mid_ntp_time(local_receive_mid_ntp_time) {} uint32_t ssrc; // Received NTP timestamp in compact representation. uint32_t received_remote_mid_ntp_time; // NTP time when the report was received in compact representation. uint32_t local_receive_mid_ntp_time; }; struct LastFirStatus { LastFirStatus(Timestamp now, uint8_t sequence_number) : request(now), sequence_number(sequence_number) {} Timestamp request; uint8_t sequence_number; }; class RttStats { public: RttStats() = default; RttStats(const RttStats&) = default; RttStats& operator=(const RttStats&) = default; void AddRtt(TimeDelta rtt); TimeDelta last_rtt() const { return last_rtt_; } TimeDelta average_rtt() const { return sum_rtt_ / num_rtts_; } private: TimeDelta last_rtt_ = TimeDelta::Zero(); TimeDelta sum_rtt_ = TimeDelta::Zero(); size_t num_rtts_ = 0; }; bool ParseCompoundPacket(rtc::ArrayView packet, PacketInformation* packet_information); void TriggerCallbacksFromRtcpPacket( const PacketInformation& packet_information); TmmbrInformation* FindOrCreateTmmbrInfo(uint32_t remote_ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); // Update TmmbrInformation (if present) is alive. void UpdateTmmbrRemoteIsAlive(uint32_t remote_ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); TmmbrInformation* GetTmmbrInformation(uint32_t remote_ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleSenderReport(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleReceiverReport(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandleReportBlock(const rtcp::ReportBlock& report_block, PacketInformation* packet_information, uint32_t remote_ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleSdes(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleXr(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information, bool& contains_dlrr, uint32_t& ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandleXrReceiveReferenceTime(uint32_t sender_ssrc, const rtcp::Rrtr& rrtr) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandleXrDlrrReportBlock(uint32_t ssrc, const rtcp::ReceiveTimeInfo& rti) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandleXrTargetBitrate(uint32_t ssrc, const rtcp::TargetBitrate& target_bitrate, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleNack(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleApp(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleBye(const rtcp::CommonHeader& rtcp_block) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandlePli(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandlePsfbApp(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleTmmbr(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleTmmbn(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleSrReq(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool HandleFir(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); void HandleTransportFeedback(const rtcp::CommonHeader& rtcp_block, PacketInformation* packet_information) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool RtcpRrTimeoutLocked(Timestamp now) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); bool RtcpRrSequenceNumberTimeoutLocked(Timestamp now) RTC_EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); Clock* const clock_; const bool receiver_only_; ModuleRtpRtcp* const rtp_rtcp_; // The set of registered local SSRCs. RegisteredSsrcs registered_ssrcs_; NetworkLinkRtcpObserver* const network_link_rtcp_observer_; RtcpEventObserver* const rtcp_event_observer_; RtcpIntraFrameObserver* const rtcp_intra_frame_observer_; RtcpLossNotificationObserver* const rtcp_loss_notification_observer_; NetworkStateEstimateObserver* const network_state_estimate_observer_; VideoBitrateAllocationObserver* const bitrate_allocation_observer_; const TimeDelta report_interval_; mutable Mutex rtcp_receiver_lock_; uint32_t remote_ssrc_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Received sender report. RtpRtcpInterface::SenderReportStats remote_sender_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Received RRTR information in ascending receive time order. std::list received_rrtrs_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Received RRTR information mapped by remote ssrc. flat_map::iterator> received_rrtrs_ssrc_it_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Estimated rtt, nullopt when there is no valid estimate. bool xr_rrtr_status_ RTC_GUARDED_BY(rtcp_receiver_lock_); absl::optional xr_rr_rtt_; Timestamp oldest_tmmbr_info_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Mapped by remote ssrc. flat_map tmmbr_infos_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Round-Trip Time per remote sender ssrc. flat_map rtts_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Non-sender Round-trip time per remote ssrc. flat_map non_sender_rtts_ RTC_GUARDED_BY(rtcp_receiver_lock_); // Report blocks per local source ssrc. flat_map received_report_blocks_ RTC_GUARDED_BY(rtcp_receiver_lock_); flat_map last_fir_ RTC_GUARDED_BY(rtcp_receiver_lock_); // The last time we received an RTCP Report block for this module. Timestamp last_received_rb_ RTC_GUARDED_BY(rtcp_receiver_lock_) = Timestamp::PlusInfinity(); // The time we last received an RTCP RR telling we have successfully // delivered RTP packet to the remote side. Timestamp last_increased_sequence_number_ = Timestamp::PlusInfinity(); RtcpCnameCallback* const cname_callback_; ReportBlockDataObserver* const report_block_data_observer_; RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; RtcpPacketTypeCounter packet_type_counter_; RtcpNackStats nack_stats_; size_t num_skipped_packets_; Timestamp last_skipped_packets_warning_; }; } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_