blob: 9864d4e51bb247cabfb0224101d24a3b9781c96e [file] [log] [blame]
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +00001/*
2 * Copyright (c) 2012 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
Peter Boström7623ce42015-12-09 12:13:30 +010011#include "webrtc/video/call_stats.h"
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000012
Peter Boström7623ce42015-12-09 12:13:30 +010013#include <algorithm>
14
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010015#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020016#include "webrtc/rtc_base/checks.h"
17#include "webrtc/rtc_base/constructormagic.h"
sprange2d83d62016-02-19 09:03:26 -080018#include "webrtc/system_wrappers/include/metrics.h"
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000019
20namespace webrtc {
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000021namespace {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000022// Time interval for updating the observers.
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000023const int64_t kUpdateIntervalMs = 1000;
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000024// Weight factor to apply to the average rtt.
25const float kWeightFactor = 0.3f;
26
27void RemoveOldReports(int64_t now, std::list<CallStats::RttTime>* reports) {
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000028 // A rtt report is considered valid for this long.
29 const int64_t kRttTimeoutMs = 1500;
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000030 while (!reports->empty() &&
31 (now - reports->front().time) > kRttTimeoutMs) {
32 reports->pop_front();
33 }
34}
35
pkasting@chromium.org16825b12015-01-12 21:51:21 +000036int64_t GetMaxRttMs(std::list<CallStats::RttTime>* reports) {
sprange2d83d62016-02-19 09:03:26 -080037 if (reports->empty())
38 return -1;
pkasting@chromium.org16825b12015-01-12 21:51:21 +000039 int64_t max_rtt_ms = 0;
sprange2d83d62016-02-19 09:03:26 -080040 for (const CallStats::RttTime& rtt_time : *reports)
41 max_rtt_ms = std::max(rtt_time.rtt, max_rtt_ms);
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000042 return max_rtt_ms;
43}
44
pkasting@chromium.org16825b12015-01-12 21:51:21 +000045int64_t GetAvgRttMs(std::list<CallStats::RttTime>* reports) {
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000046 if (reports->empty()) {
sprange2d83d62016-02-19 09:03:26 -080047 return -1;
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000048 }
pkasting@chromium.org16825b12015-01-12 21:51:21 +000049 int64_t sum = 0;
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000050 for (std::list<CallStats::RttTime>::const_iterator it = reports->begin();
51 it != reports->end(); ++it) {
52 sum += it->rtt;
53 }
54 return sum / reports->size();
55}
56
pkasting@chromium.org16825b12015-01-12 21:51:21 +000057void UpdateAvgRttMs(std::list<CallStats::RttTime>* reports, int64_t* avg_rtt) {
sprange2d83d62016-02-19 09:03:26 -080058 int64_t cur_rtt_ms = GetAvgRttMs(reports);
59 if (cur_rtt_ms == -1) {
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000060 // Reset.
sprange2d83d62016-02-19 09:03:26 -080061 *avg_rtt = -1;
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000062 return;
63 }
sprange2d83d62016-02-19 09:03:26 -080064 if (*avg_rtt == -1) {
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000065 // Initialize.
66 *avg_rtt = cur_rtt_ms;
67 return;
68 }
69 *avg_rtt = *avg_rtt * (1.0f - kWeightFactor) + cur_rtt_ms * kWeightFactor;
70}
71} // namespace
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000072
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000073class RtcpObserver : public RtcpRttStats {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000074 public:
75 explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
76 virtual ~RtcpObserver() {}
77
pkasting@chromium.org16825b12015-01-12 21:51:21 +000078 virtual void OnRttUpdate(int64_t rtt) {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000079 owner_->OnRttUpdate(rtt);
80 }
81
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000082 // Returns the average RTT.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000083 virtual int64_t LastProcessedRtt() const {
asapersson@webrtc.org8084f952014-12-10 11:04:13 +000084 return owner_->avg_rtt_ms();
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000085 }
86
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000087 private:
88 CallStats* owner_;
89
henrikg3c089d72015-09-16 05:37:44 -070090 RTC_DISALLOW_COPY_AND_ASSIGN(RtcpObserver);
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000091};
92
Peter Boströmd3c94472015-12-09 11:20:58 +010093CallStats::CallStats(Clock* clock)
94 : clock_(clock),
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000095 rtcp_rtt_stats_(new RtcpObserver(this)),
Peter Boströmd3c94472015-12-09 11:20:58 +010096 last_process_time_(clock_->TimeInMilliseconds()),
sprange2d83d62016-02-19 09:03:26 -080097 max_rtt_ms_(-1),
98 avg_rtt_ms_(-1),
99 sum_avg_rtt_ms_(0),
100 num_avg_rtt_(0),
101 time_of_first_rtt_ms_(-1) {}
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000102
103CallStats::~CallStats() {
sprange2d83d62016-02-19 09:03:26 -0800104 RTC_DCHECK(observers_.empty());
105 UpdateHistograms();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000106}
107
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +0000108int64_t CallStats::TimeUntilNextProcess() {
Peter Boströmd3c94472015-12-09 11:20:58 +0100109 return last_process_time_ + kUpdateIntervalMs - clock_->TimeInMilliseconds();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000110}
111
pbosa26ac922016-02-25 04:50:01 -0800112void CallStats::Process() {
Tommi97888bd2016-01-21 23:24:59 +0100113 rtc::CritScope cs(&crit_);
Peter Boströmd3c94472015-12-09 11:20:58 +0100114 int64_t now = clock_->TimeInMilliseconds();
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000115 if (now < last_process_time_ + kUpdateIntervalMs)
pbosa26ac922016-02-25 04:50:01 -0800116 return;
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000117
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000118 last_process_time_ = now;
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000119
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000120 RemoveOldReports(now, &reports_);
121 max_rtt_ms_ = GetMaxRttMs(&reports_);
122 UpdateAvgRttMs(&reports_, &avg_rtt_ms_);
stefan@webrtc.org8ca8a712013-04-23 16:48:32 +0000123
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000124 // If there is a valid rtt, update all observers with the max rtt.
sprange2d83d62016-02-19 09:03:26 -0800125 if (max_rtt_ms_ >= 0) {
126 RTC_DCHECK_GE(avg_rtt_ms_, 0);
stefan@webrtc.org8ca8a712013-04-23 16:48:32 +0000127 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
128 it != observers_.end(); ++it) {
stefan2328a942015-08-07 04:27:51 -0700129 (*it)->OnRttUpdate(avg_rtt_ms_, max_rtt_ms_);
stefan@webrtc.org8ca8a712013-04-23 16:48:32 +0000130 }
sprange2d83d62016-02-19 09:03:26 -0800131 // Sum for Histogram of average RTT reported over the entire call.
132 sum_avg_rtt_ms_ += avg_rtt_ms_;
133 ++num_avg_rtt_;
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000134 }
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000135}
136
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000137int64_t CallStats::avg_rtt_ms() const {
Tommi97888bd2016-01-21 23:24:59 +0100138 rtc::CritScope cs(&crit_);
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000139 return avg_rtt_ms_;
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +0000140}
141
142RtcpRttStats* CallStats::rtcp_rtt_stats() const {
143 return rtcp_rtt_stats_.get();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000144}
145
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000146void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
Tommi97888bd2016-01-21 23:24:59 +0100147 rtc::CritScope cs(&crit_);
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000148 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000149 it != observers_.end(); ++it) {
150 if (*it == observer)
151 return;
152 }
153 observers_.push_back(observer);
154}
155
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000156void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
Tommi97888bd2016-01-21 23:24:59 +0100157 rtc::CritScope cs(&crit_);
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000158 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000159 it != observers_.end(); ++it) {
160 if (*it == observer) {
161 observers_.erase(it);
162 return;
163 }
164 }
165}
166
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000167void CallStats::OnRttUpdate(int64_t rtt) {
Tommi97888bd2016-01-21 23:24:59 +0100168 rtc::CritScope cs(&crit_);
sprange2d83d62016-02-19 09:03:26 -0800169 int64_t now_ms = clock_->TimeInMilliseconds();
170 reports_.push_back(RttTime(rtt, now_ms));
171 if (time_of_first_rtt_ms_ == -1)
172 time_of_first_rtt_ms_ = now_ms;
173}
174
175void CallStats::UpdateHistograms() {
176 rtc::CritScope cs(&crit_);
177 if (time_of_first_rtt_ms_ == -1 || num_avg_rtt_ < 1)
178 return;
179
180 int64_t elapsed_sec =
181 (clock_->TimeInMilliseconds() - time_of_first_rtt_ms_) / 1000;
182 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
183 int64_t avg_rtt_ms = (sum_avg_rtt_ms_ + num_avg_rtt_ / 2) / num_avg_rtt_;
asapersson1d02d3e2016-09-09 22:40:25 -0700184 RTC_HISTOGRAM_COUNTS_10000(
sprange2d83d62016-02-19 09:03:26 -0800185 "WebRTC.Video.AverageRoundTripTimeInMilliseconds", avg_rtt_ms);
186 }
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000187}
188
189} // namespace webrtc