1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ 12 #define MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ 13 14 #include <algorithm> 15 #include <functional> 16 #include <map> 17 #include <memory> 18 #include <utility> 19 #include <vector> 20 #include <cstdint> 21 22 #include "absl/types/optional.h" 23 #include "modules/include/module_common_types_public.h" 24 #include "modules/rtp_rtcp/include/receive_statistics.h" 25 #include "rtc_base/rate_statistics.h" 26 #include "rtc_base/synchronization/mutex.h" 27 #include "rtc_base/thread_annotations.h" 28 29 namespace webrtc { 30 31 // Extends StreamStatistician with methods needed by the implementation. 32 class StreamStatisticianImplInterface : public StreamStatistician { 33 public: 34 virtual ~StreamStatisticianImplInterface() = default; 35 virtual bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) = 0; 36 virtual void SetMaxReorderingThreshold(int max_reordering_threshold) = 0; 37 virtual void EnableRetransmitDetection(bool enable) = 0; 38 virtual void UpdateCounters(const RtpPacketReceived& packet) = 0; 39 }; 40 41 // Thread-compatible implementation of StreamStatisticianImplInterface. 42 class StreamStatisticianImpl : public StreamStatisticianImplInterface { 43 public: 44 StreamStatisticianImpl(uint32_t ssrc, 45 Clock* clock, 46 int max_reordering_threshold); 47 ~StreamStatisticianImpl() override; 48 49 // Implements StreamStatistician 50 RtpReceiveStats GetStats() const override; 51 absl::optional<int> GetFractionLostInPercent() const override; 52 StreamDataCounters GetReceiveStreamDataCounters() const override; 53 uint32_t BitrateReceived() const override; 54 55 // Implements StreamStatisticianImplInterface 56 bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override; 57 void SetMaxReorderingThreshold(int max_reordering_threshold) override; 58 void EnableRetransmitDetection(bool enable) override; 59 // Updates StreamStatistician for incoming packets. 60 void UpdateCounters(const RtpPacketReceived& packet) override; 61 62 private: 63 bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet, 64 int64_t now_ms) const; 65 RtcpStatistics CalculateRtcpStatistics(); 66 void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms); 67 // Updates StreamStatistician for out of order packets. 68 // Returns true if packet considered to be out of order. 69 bool UpdateOutOfOrder(const RtpPacketReceived& packet, 70 int64_t sequence_number, 71 int64_t now_ms); 72 // Checks if this StreamStatistician received any rtp packets. ReceivedRtpPacket()73 bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; } 74 75 const uint32_t ssrc_; 76 Clock* const clock_; 77 // Delta used to map internal timestamps to Unix epoch ones. 78 const int64_t delta_internal_unix_epoch_ms_; 79 RateStatistics incoming_bitrate_; 80 // In number of packets or sequence numbers. 81 int max_reordering_threshold_; 82 bool enable_retransmit_detection_; 83 84 // Stats on received RTP packets. 85 uint32_t jitter_q4_; 86 // Cumulative loss according to RFC 3550, which may be negative (and often is, 87 // if packets are reordered and there are non-RTX retransmissions). 88 int32_t cumulative_loss_; 89 // Offset added to outgoing rtcp reports, to make ensure that the reported 90 // cumulative loss is non-negative. Reports with negative values confuse some 91 // senders, in particular, our own loss-based bandwidth estimator. 92 int32_t cumulative_loss_rtcp_offset_; 93 94 int64_t last_receive_time_ms_; 95 uint32_t last_received_timestamp_; 96 SequenceNumberUnwrapper seq_unwrapper_; 97 int64_t received_seq_first_; 98 int64_t received_seq_max_; 99 // Assume that the other side restarted when there are two sequential packets 100 // with large jump from received_seq_max_. 101 absl::optional<uint16_t> received_seq_out_of_order_; 102 103 // Current counter values. 104 StreamDataCounters receive_counters_; 105 106 // Counter values when we sent the last report. 107 int32_t last_report_cumulative_loss_; 108 int64_t last_report_seq_max_; 109 }; 110 111 // Thread-safe implementation of StreamStatisticianImplInterface. 112 class StreamStatisticianLocked : public StreamStatisticianImplInterface { 113 public: StreamStatisticianLocked(uint32_t ssrc,Clock * clock,int max_reordering_threshold)114 StreamStatisticianLocked(uint32_t ssrc, 115 Clock* clock, 116 int max_reordering_threshold) 117 : impl_(ssrc, clock, max_reordering_threshold) {} 118 ~StreamStatisticianLocked() override = default; 119 GetStats()120 RtpReceiveStats GetStats() const override { 121 MutexLock lock(&stream_lock_); 122 return impl_.GetStats(); 123 } GetFractionLostInPercent()124 absl::optional<int> GetFractionLostInPercent() const override { 125 MutexLock lock(&stream_lock_); 126 return impl_.GetFractionLostInPercent(); 127 } GetReceiveStreamDataCounters()128 StreamDataCounters GetReceiveStreamDataCounters() const override { 129 MutexLock lock(&stream_lock_); 130 return impl_.GetReceiveStreamDataCounters(); 131 } BitrateReceived()132 uint32_t BitrateReceived() const override { 133 MutexLock lock(&stream_lock_); 134 return impl_.BitrateReceived(); 135 } GetActiveStatisticsAndReset(RtcpStatistics * statistics)136 bool GetActiveStatisticsAndReset(RtcpStatistics* statistics) override { 137 MutexLock lock(&stream_lock_); 138 return impl_.GetActiveStatisticsAndReset(statistics); 139 } SetMaxReorderingThreshold(int max_reordering_threshold)140 void SetMaxReorderingThreshold(int max_reordering_threshold) override { 141 MutexLock lock(&stream_lock_); 142 return impl_.SetMaxReorderingThreshold(max_reordering_threshold); 143 } EnableRetransmitDetection(bool enable)144 void EnableRetransmitDetection(bool enable) override { 145 MutexLock lock(&stream_lock_); 146 return impl_.EnableRetransmitDetection(enable); 147 } UpdateCounters(const RtpPacketReceived & packet)148 void UpdateCounters(const RtpPacketReceived& packet) override { 149 MutexLock lock(&stream_lock_); 150 return impl_.UpdateCounters(packet); 151 } 152 153 private: 154 mutable Mutex stream_lock_; 155 StreamStatisticianImpl impl_ RTC_GUARDED_BY(&stream_lock_); 156 }; 157 158 // Thread-compatible implementation. 159 class ReceiveStatisticsImpl : public ReceiveStatistics { 160 public: 161 ReceiveStatisticsImpl( 162 Clock* clock, 163 std::function<std::unique_ptr<StreamStatisticianImplInterface>( 164 uint32_t ssrc, 165 Clock* clock, 166 int max_reordering_threshold)> stream_statistician_factory); 167 ~ReceiveStatisticsImpl() override = default; 168 169 // Implements ReceiveStatisticsProvider. 170 std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override; 171 172 // Implements RtpPacketSinkInterface 173 void OnRtpPacket(const RtpPacketReceived& packet) override; 174 175 // Implements ReceiveStatistics. 176 StreamStatistician* GetStatistician(uint32_t ssrc) const override; 177 void SetMaxReorderingThreshold(int max_reordering_threshold) override; 178 void SetMaxReorderingThreshold(uint32_t ssrc, 179 int max_reordering_threshold) override; 180 void EnableRetransmitDetection(uint32_t ssrc, bool enable) override; 181 182 private: 183 StreamStatisticianImplInterface* GetOrCreateStatistician(uint32_t ssrc); 184 185 Clock* const clock_; 186 std::function<std::unique_ptr<StreamStatisticianImplInterface>( 187 uint32_t ssrc, 188 Clock* clock, 189 int max_reordering_threshold)> 190 stream_statistician_factory_; 191 uint32_t last_returned_ssrc_; 192 int max_reordering_threshold_; 193 std::map<uint32_t, std::unique_ptr<StreamStatisticianImplInterface>> 194 statisticians_; 195 }; 196 197 // Thread-safe implementation wrapping access to ReceiveStatisticsImpl with a 198 // mutex. 199 class ReceiveStatisticsLocked : public ReceiveStatistics { 200 public: ReceiveStatisticsLocked(Clock * clock,std::function<std::unique_ptr<StreamStatisticianImplInterface> (uint32_t ssrc,Clock * clock,int max_reordering_threshold)> stream_statitician_factory)201 explicit ReceiveStatisticsLocked( 202 Clock* clock, 203 std::function<std::unique_ptr<StreamStatisticianImplInterface>( 204 uint32_t ssrc, 205 Clock* clock, 206 int max_reordering_threshold)> stream_statitician_factory) 207 : impl_(clock, std::move(stream_statitician_factory)) {} 208 ~ReceiveStatisticsLocked() override = default; RtcpReportBlocks(size_t max_blocks)209 std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override { 210 MutexLock lock(&receive_statistics_lock_); 211 return impl_.RtcpReportBlocks(max_blocks); 212 } OnRtpPacket(const RtpPacketReceived & packet)213 void OnRtpPacket(const RtpPacketReceived& packet) override { 214 MutexLock lock(&receive_statistics_lock_); 215 return impl_.OnRtpPacket(packet); 216 } GetStatistician(uint32_t ssrc)217 StreamStatistician* GetStatistician(uint32_t ssrc) const override { 218 MutexLock lock(&receive_statistics_lock_); 219 return impl_.GetStatistician(ssrc); 220 } SetMaxReorderingThreshold(int max_reordering_threshold)221 void SetMaxReorderingThreshold(int max_reordering_threshold) override { 222 MutexLock lock(&receive_statistics_lock_); 223 return impl_.SetMaxReorderingThreshold(max_reordering_threshold); 224 } SetMaxReorderingThreshold(uint32_t ssrc,int max_reordering_threshold)225 void SetMaxReorderingThreshold(uint32_t ssrc, 226 int max_reordering_threshold) override { 227 MutexLock lock(&receive_statistics_lock_); 228 return impl_.SetMaxReorderingThreshold(ssrc, max_reordering_threshold); 229 } EnableRetransmitDetection(uint32_t ssrc,bool enable)230 void EnableRetransmitDetection(uint32_t ssrc, bool enable) override { 231 MutexLock lock(&receive_statistics_lock_); 232 return impl_.EnableRetransmitDetection(ssrc, enable); 233 } 234 235 private: 236 mutable Mutex receive_statistics_lock_; 237 ReceiveStatisticsImpl impl_ RTC_GUARDED_BY(&receive_statistics_lock_); 238 }; 239 240 } // namespace webrtc 241 #endif // MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ 242