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