blob: 1ee462555299642674c29f371d552ca1697844cc [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
sprange2d83d62016-02-19 09:03:26 -080015#include "webrtc/base/checks.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010016#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
sprange2d83d62016-02-19 09:03:26 -080017#include "webrtc/system_wrappers/include/metrics.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010018#include "webrtc/system_wrappers/include/tick_util.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
112int32_t 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)
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000116 return 0;
117
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 return 0;
136}
137
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000138int64_t CallStats::avg_rtt_ms() const {
Tommi97888bd2016-01-21 23:24:59 +0100139 rtc::CritScope cs(&crit_);
asapersson@webrtc.org8084f952014-12-10 11:04:13 +0000140 return avg_rtt_ms_;
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +0000141}
142
143RtcpRttStats* CallStats::rtcp_rtt_stats() const {
144 return rtcp_rtt_stats_.get();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000145}
146
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000147void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
Tommi97888bd2016-01-21 23:24:59 +0100148 rtc::CritScope cs(&crit_);
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000149 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000150 it != observers_.end(); ++it) {
151 if (*it == observer)
152 return;
153 }
154 observers_.push_back(observer);
155}
156
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000157void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
Tommi97888bd2016-01-21 23:24:59 +0100158 rtc::CritScope cs(&crit_);
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000159 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000160 it != observers_.end(); ++it) {
161 if (*it == observer) {
162 observers_.erase(it);
163 return;
164 }
165 }
166}
167
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000168void CallStats::OnRttUpdate(int64_t rtt) {
Tommi97888bd2016-01-21 23:24:59 +0100169 rtc::CritScope cs(&crit_);
sprange2d83d62016-02-19 09:03:26 -0800170 int64_t now_ms = clock_->TimeInMilliseconds();
171 reports_.push_back(RttTime(rtt, now_ms));
172 if (time_of_first_rtt_ms_ == -1)
173 time_of_first_rtt_ms_ = now_ms;
174}
175
176void CallStats::UpdateHistograms() {
177 rtc::CritScope cs(&crit_);
178 if (time_of_first_rtt_ms_ == -1 || num_avg_rtt_ < 1)
179 return;
180
181 int64_t elapsed_sec =
182 (clock_->TimeInMilliseconds() - time_of_first_rtt_ms_) / 1000;
183 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
184 int64_t avg_rtt_ms = (sum_avg_rtt_ms_ + num_avg_rtt_ / 2) / num_avg_rtt_;
185 RTC_HISTOGRAM_COUNTS_10000(
186 "WebRTC.Video.AverageRoundTripTimeInMilliseconds", avg_rtt_ms);
187 }
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000188}
189
190} // namespace webrtc