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