blob: 1a70fe4ad7e47565fded0a47a26ce69e43b93cce [file] [log] [blame]
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
12#define MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
wu@webrtc.org822fbd82013-08-15 23:38:54 +000013
wu@webrtc.org822fbd82013-08-15 23:38:54 +000014#include <algorithm>
Per Kjellanderee8cd202021-03-10 12:31:38 +010015#include <functional>
Per Kjellanderee8cd202021-03-10 12:31:38 +010016#include <memory>
17#include <utility>
danilchap0bc84232017-08-11 08:12:54 -070018#include <vector>
wu@webrtc.org822fbd82013-08-15 23:38:54 +000019
Danil Chapovalovb438b5a2018-12-05 14:55:46 +000020#include "absl/types/optional.h"
21#include "modules/include/module_common_types_public.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020022#include "modules/rtp_rtcp/include/receive_statistics.h"
Danil Chapovalovb27a9f92021-05-17 14:22:02 +020023#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
Victor Boivie18649972021-07-06 22:43:47 +020024#include "rtc_base/containers/flat_map.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "rtc_base/rate_statistics.h"
Markus Handelle7c015e2020-07-07 11:44:28 +020026#include "rtc_base/synchronization/mutex.h"
Danil Chapovalovebb50c22018-11-22 14:04:02 +010027#include "rtc_base/thread_annotations.h"
wu@webrtc.org822fbd82013-08-15 23:38:54 +000028
29namespace webrtc {
30
Per Kjellanderee8cd202021-03-10 12:31:38 +010031// Extends StreamStatistician with methods needed by the implementation.
32class StreamStatisticianImplInterface : public StreamStatistician {
33 public:
34 virtual ~StreamStatisticianImplInterface() = default;
Danil Chapovalovb27a9f92021-05-17 14:22:02 +020035 virtual void MaybeAppendReportBlockAndReset(
36 std::vector<rtcp::ReportBlock>& report_blocks) = 0;
Per Kjellanderee8cd202021-03-10 12:31:38 +010037 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.
43class StreamStatisticianImpl : public StreamStatisticianImplInterface {
wu@webrtc.org822fbd82013-08-15 23:38:54 +000044 public:
danilchapec86be02017-08-14 05:51:02 -070045 StreamStatisticianImpl(uint32_t ssrc,
46 Clock* clock,
Niels Möllerd7819652019-08-13 14:43:02 +020047 int max_reordering_threshold);
Danil Chapovalov2a5ce2b2018-02-07 09:38:31 +010048 ~StreamStatisticianImpl() override;
wu@webrtc.org822fbd82013-08-15 23:38:54 +000049
Per Kjellanderee8cd202021-03-10 12:31:38 +010050 // Implements StreamStatistician
Niels Möllerd77cc242019-08-22 09:40:25 +020051 RtpReceiveStats GetStats() const override;
Niels Möller9a9f18a2019-08-02 13:52:37 +020052 absl::optional<int> GetFractionLostInPercent() const override;
Niels Möller58b496b2019-08-12 12:16:31 +020053 StreamDataCounters GetReceiveStreamDataCounters() const override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000054 uint32_t BitrateReceived() const override;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000055
Per Kjellanderee8cd202021-03-10 12:31:38 +010056 // Implements StreamStatisticianImplInterface
Danil Chapovalovb27a9f92021-05-17 14:22:02 +020057 void MaybeAppendReportBlockAndReset(
58 std::vector<rtcp::ReportBlock>& report_blocks) override;
Per Kjellanderee8cd202021-03-10 12:31:38 +010059 void SetMaxReorderingThreshold(int max_reordering_threshold) override;
60 void EnableRetransmitDetection(bool enable) override;
Niels Möller1a3859c2019-09-04 09:43:15 +020061 // Updates StreamStatistician for incoming packets.
Per Kjellanderee8cd202021-03-10 12:31:38 +010062 void UpdateCounters(const RtpPacketReceived& packet) override;
Niels Möller1a3859c2019-09-04 09:43:15 +020063
wu@webrtc.org822fbd82013-08-15 23:38:54 +000064 private:
Danil Chapovalov44727b42018-11-22 11:28:45 +010065 bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
Per Kjellanderee8cd202021-03-10 12:31:38 +010066 int64_t now_ms) const;
Per Kjellanderee8cd202021-03-10 12:31:38 +010067 void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +000068 // Updates StreamStatistician for out of order packets.
69 // Returns true if packet considered to be out of order.
70 bool UpdateOutOfOrder(const RtpPacketReceived& packet,
71 int64_t sequence_number,
Per Kjellanderee8cd202021-03-10 12:31:38 +010072 int64_t now_ms);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +000073 // Checks if this StreamStatistician received any rtp packets.
Per Kjellanderee8cd202021-03-10 12:31:38 +010074 bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000075
danilchapec86be02017-08-14 05:51:02 -070076 const uint32_t ssrc_;
sprangcd349d92016-07-13 09:11:28 -070077 Clock* const clock_;
Alessio Bazzica5cf8c2c2021-03-24 08:51:26 +010078 // Delta used to map internal timestamps to Unix epoch ones.
79 const int64_t delta_internal_unix_epoch_ms_;
Per Kjellanderee8cd202021-03-10 12:31:38 +010080 RateStatistics incoming_bitrate_;
Niels Möllerb615d1a2018-08-27 12:32:21 +020081 // In number of packets or sequence numbers.
Per Kjellanderee8cd202021-03-10 12:31:38 +010082 int max_reordering_threshold_;
83 bool enable_retransmit_detection_;
Danil Chapovalovb27a9f92021-05-17 14:22:02 +020084 bool cumulative_loss_is_capped_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000085
wu@webrtc.org822fbd82013-08-15 23:38:54 +000086 // Stats on received RTP packets.
Per Kjellanderee8cd202021-03-10 12:31:38 +010087 uint32_t jitter_q4_;
Niels Möller1a3859c2019-09-04 09:43:15 +020088 // Cumulative loss according to RFC 3550, which may be negative (and often is,
89 // if packets are reordered and there are non-RTX retransmissions).
Per Kjellanderee8cd202021-03-10 12:31:38 +010090 int32_t cumulative_loss_;
Niels Möller1a3859c2019-09-04 09:43:15 +020091 // Offset added to outgoing rtcp reports, to make ensure that the reported
92 // cumulative loss is non-negative. Reports with negative values confuse some
93 // senders, in particular, our own loss-based bandwidth estimator.
Per Kjellanderee8cd202021-03-10 12:31:38 +010094 int32_t cumulative_loss_rtcp_offset_;
wu@webrtc.org822fbd82013-08-15 23:38:54 +000095
Per Kjellanderee8cd202021-03-10 12:31:38 +010096 int64_t last_receive_time_ms_;
97 uint32_t last_received_timestamp_;
98 SequenceNumberUnwrapper seq_unwrapper_;
99 int64_t received_seq_first_;
100 int64_t received_seq_max_;
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000101 // Assume that the other side restarted when there are two sequential packets
102 // with large jump from received_seq_max_.
Per Kjellanderee8cd202021-03-10 12:31:38 +0100103 absl::optional<uint16_t> received_seq_out_of_order_;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000104
105 // Current counter values.
Per Kjellanderee8cd202021-03-10 12:31:38 +0100106 StreamDataCounters receive_counters_;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000107
Qingsi Wang2370b082018-08-21 14:24:26 -0700108 // Counter values when we sent the last report.
Per Kjellanderee8cd202021-03-10 12:31:38 +0100109 int32_t last_report_cumulative_loss_;
110 int64_t last_report_seq_max_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000111};
112
Per Kjellanderee8cd202021-03-10 12:31:38 +0100113// Thread-safe implementation of StreamStatisticianImplInterface.
114class StreamStatisticianLocked : public StreamStatisticianImplInterface {
115 public:
116 StreamStatisticianLocked(uint32_t ssrc,
117 Clock* clock,
118 int max_reordering_threshold)
119 : impl_(ssrc, clock, max_reordering_threshold) {}
120 ~StreamStatisticianLocked() override = default;
121
122 RtpReceiveStats GetStats() const override {
123 MutexLock lock(&stream_lock_);
124 return impl_.GetStats();
125 }
126 absl::optional<int> GetFractionLostInPercent() const override {
127 MutexLock lock(&stream_lock_);
128 return impl_.GetFractionLostInPercent();
129 }
130 StreamDataCounters GetReceiveStreamDataCounters() const override {
131 MutexLock lock(&stream_lock_);
132 return impl_.GetReceiveStreamDataCounters();
133 }
134 uint32_t BitrateReceived() const override {
135 MutexLock lock(&stream_lock_);
136 return impl_.BitrateReceived();
137 }
Danil Chapovalovb27a9f92021-05-17 14:22:02 +0200138 void MaybeAppendReportBlockAndReset(
139 std::vector<rtcp::ReportBlock>& report_blocks) override {
Per Kjellanderee8cd202021-03-10 12:31:38 +0100140 MutexLock lock(&stream_lock_);
Danil Chapovalovb27a9f92021-05-17 14:22:02 +0200141 impl_.MaybeAppendReportBlockAndReset(report_blocks);
Per Kjellanderee8cd202021-03-10 12:31:38 +0100142 }
143 void SetMaxReorderingThreshold(int max_reordering_threshold) override {
144 MutexLock lock(&stream_lock_);
145 return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
146 }
147 void EnableRetransmitDetection(bool enable) override {
148 MutexLock lock(&stream_lock_);
149 return impl_.EnableRetransmitDetection(enable);
150 }
151 void UpdateCounters(const RtpPacketReceived& packet) override {
152 MutexLock lock(&stream_lock_);
153 return impl_.UpdateCounters(packet);
154 }
155
156 private:
157 mutable Mutex stream_lock_;
158 StreamStatisticianImpl impl_ RTC_GUARDED_BY(&stream_lock_);
159};
160
161// Thread-compatible implementation.
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100162class ReceiveStatisticsImpl : public ReceiveStatistics {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000163 public:
Per Kjellanderee8cd202021-03-10 12:31:38 +0100164 ReceiveStatisticsImpl(
165 Clock* clock,
166 std::function<std::unique_ptr<StreamStatisticianImplInterface>(
167 uint32_t ssrc,
168 Clock* clock,
169 int max_reordering_threshold)> stream_statistician_factory);
170 ~ReceiveStatisticsImpl() override = default;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000171
Niels Möllerdbb988b2018-11-15 08:05:16 +0100172 // Implements ReceiveStatisticsProvider.
danilchap0bc84232017-08-11 08:12:54 -0700173 std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override;
174
Niels Möllerdbb988b2018-11-15 08:05:16 +0100175 // Implements RtpPacketSinkInterface
Niels Möller1f3206c2018-09-14 08:26:32 +0200176 void OnRtpPacket(const RtpPacketReceived& packet) override;
177
Niels Möllerdbb988b2018-11-15 08:05:16 +0100178 // Implements ReceiveStatistics.
Per Kjellanderee8cd202021-03-10 12:31:38 +0100179 StreamStatistician* GetStatistician(uint32_t ssrc) const override;
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000180 void SetMaxReorderingThreshold(int max_reordering_threshold) override;
Niels Möller87da1092019-05-24 14:04:28 +0200181 void SetMaxReorderingThreshold(uint32_t ssrc,
182 int max_reordering_threshold) override;
Niels Möller5304a322018-08-27 13:27:05 +0200183 void EnableRetransmitDetection(uint32_t ssrc, bool enable) override;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000184
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000185 private:
Per Kjellanderee8cd202021-03-10 12:31:38 +0100186 StreamStatisticianImplInterface* GetOrCreateStatistician(uint32_t ssrc);
Niels Möller87da1092019-05-24 14:04:28 +0200187
sprangcd349d92016-07-13 09:11:28 -0700188 Clock* const clock_;
Per Kjellanderee8cd202021-03-10 12:31:38 +0100189 std::function<std::unique_ptr<StreamStatisticianImplInterface>(
190 uint32_t ssrc,
191 Clock* clock,
192 int max_reordering_threshold)>
193 stream_statistician_factory_;
Victor Boivieb2f8c162021-04-28 12:02:37 +0200194 // The index within `all_ssrcs_` that was last returned.
195 size_t last_returned_ssrc_idx_;
196 std::vector<uint32_t> all_ssrcs_;
Per Kjellanderee8cd202021-03-10 12:31:38 +0100197 int max_reordering_threshold_;
Victor Boivie18649972021-07-06 22:43:47 +0200198 flat_map<uint32_t /*ssrc*/, std::unique_ptr<StreamStatisticianImplInterface>>
Per Kjellanderee8cd202021-03-10 12:31:38 +0100199 statisticians_;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000200};
Per Kjellanderee8cd202021-03-10 12:31:38 +0100201
202// Thread-safe implementation wrapping access to ReceiveStatisticsImpl with a
203// mutex.
204class ReceiveStatisticsLocked : public ReceiveStatistics {
205 public:
206 explicit ReceiveStatisticsLocked(
207 Clock* clock,
208 std::function<std::unique_ptr<StreamStatisticianImplInterface>(
209 uint32_t ssrc,
210 Clock* clock,
211 int max_reordering_threshold)> stream_statitician_factory)
212 : impl_(clock, std::move(stream_statitician_factory)) {}
213 ~ReceiveStatisticsLocked() override = default;
214 std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override {
215 MutexLock lock(&receive_statistics_lock_);
216 return impl_.RtcpReportBlocks(max_blocks);
217 }
218 void OnRtpPacket(const RtpPacketReceived& packet) override {
219 MutexLock lock(&receive_statistics_lock_);
220 return impl_.OnRtpPacket(packet);
221 }
222 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
223 MutexLock lock(&receive_statistics_lock_);
224 return impl_.GetStatistician(ssrc);
225 }
226 void SetMaxReorderingThreshold(int max_reordering_threshold) override {
227 MutexLock lock(&receive_statistics_lock_);
228 return impl_.SetMaxReorderingThreshold(max_reordering_threshold);
229 }
230 void SetMaxReorderingThreshold(uint32_t ssrc,
231 int max_reordering_threshold) override {
232 MutexLock lock(&receive_statistics_lock_);
233 return impl_.SetMaxReorderingThreshold(ssrc, max_reordering_threshold);
234 }
235 void EnableRetransmitDetection(uint32_t ssrc, bool enable) override {
236 MutexLock lock(&receive_statistics_lock_);
237 return impl_.EnableRetransmitDetection(ssrc, enable);
238 }
239
240 private:
241 mutable Mutex receive_statistics_lock_;
242 ReceiveStatisticsImpl impl_ RTC_GUARDED_BY(&receive_statistics_lock_);
243};
244
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000245} // namespace webrtc
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200246#endif // MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_