1b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org/* 2b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * 4b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * Use of this source code is governed by a BSD-style license 5b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * that can be found in the LICENSE file in the root of the source 6b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * tree. An additional intellectual property rights grant can be found 7b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * in the file PATENTS. All contributing project authors may 8b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org */ 10b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 117623ce4aeb9130c937ba5836490cbb3a35679e79Peter Boström#include "webrtc/video/call_stats.h" 12b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h> 14b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 157623ce4aeb9130c937ba5836490cbb3a35679e79Peter Boström#include <algorithm> 167623ce4aeb9130c937ba5836490cbb3a35679e79Peter Boström 17ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 1898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 1998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h" 20b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 21b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.orgnamespace webrtc { 228084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.orgnamespace { 23b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org// Time interval for updating the observers. 240b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgconst int64_t kUpdateIntervalMs = 1000; 258084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org// Weight factor to apply to the average rtt. 268084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.orgconst float kWeightFactor = 0.3f; 278084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org 288084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.orgvoid RemoveOldReports(int64_t now, std::list<CallStats::RttTime>* reports) { 290b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org // A rtt report is considered valid for this long. 300b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org const int64_t kRttTimeoutMs = 1500; 318084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org while (!reports->empty() && 328084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org (now - reports->front().time) > kRttTimeoutMs) { 338084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org reports->pop_front(); 348084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 358084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org} 368084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org 3716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint64_t GetMaxRttMs(std::list<CallStats::RttTime>* reports) { 3816825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t max_rtt_ms = 0; 398084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org for (std::list<CallStats::RttTime>::const_iterator it = reports->begin(); 408084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org it != reports->end(); ++it) { 418084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org max_rtt_ms = std::max(it->rtt, max_rtt_ms); 428084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 438084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return max_rtt_ms; 448084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org} 458084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org 4616825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint64_t GetAvgRttMs(std::list<CallStats::RttTime>* reports) { 478084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org if (reports->empty()) { 488084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return 0; 498084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 5016825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t sum = 0; 518084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org for (std::list<CallStats::RttTime>::const_iterator it = reports->begin(); 528084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org it != reports->end(); ++it) { 538084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org sum += it->rtt; 548084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 558084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return sum / reports->size(); 568084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org} 578084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org 5816825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgvoid UpdateAvgRttMs(std::list<CallStats::RttTime>* reports, int64_t* avg_rtt) { 598084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org uint32_t cur_rtt_ms = GetAvgRttMs(reports); 608084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org if (cur_rtt_ms == 0) { 618084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org // Reset. 628084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org *avg_rtt = 0; 638084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return; 648084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 658084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org if (*avg_rtt == 0) { 668084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org // Initialize. 678084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org *avg_rtt = cur_rtt_ms; 688084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return; 698084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org } 708084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org *avg_rtt = *avg_rtt * (1.0f - kWeightFactor) + cur_rtt_ms * kWeightFactor; 718084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org} 728084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org} // namespace 73b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 741ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.orgclass RtcpObserver : public RtcpRttStats { 75b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org public: 76b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org explicit RtcpObserver(CallStats* owner) : owner_(owner) {} 77b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org virtual ~RtcpObserver() {} 78b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 7916825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org virtual void OnRttUpdate(int64_t rtt) { 80b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org owner_->OnRttUpdate(rtt); 81b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org } 82b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 838084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org // Returns the average RTT. 8416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org virtual int64_t LastProcessedRtt() const { 858084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return owner_->avg_rtt_ms(); 861ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org } 871ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org 88b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org private: 89b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org CallStats* owner_; 90b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 913c089d751ede283e21e186885eaf705c3257ccd2henrikg RTC_DISALLOW_COPY_AND_ASSIGN(RtcpObserver); 92b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org}; 93b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 94d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter BoströmCallStats::CallStats(Clock* clock) 95d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström : clock_(clock), 96d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström crit_(CriticalSectionWrapper::CreateCriticalSection()), 971ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org rtcp_rtt_stats_(new RtcpObserver(this)), 98d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström last_process_time_(clock_->TimeInMilliseconds()), 998084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org max_rtt_ms_(0), 100d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström avg_rtt_ms_(0) {} 101b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 102b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.orgCallStats::~CallStats() { 103b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org assert(observers_.empty()); 104b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 105b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 1060b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgint64_t CallStats::TimeUntilNextProcess() { 107d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström return last_process_time_ + kUpdateIntervalMs - clock_->TimeInMilliseconds(); 108b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 109b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 110b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.orgint32_t CallStats::Process() { 111b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 112d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström int64_t now = clock_->TimeInMilliseconds(); 1138084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org if (now < last_process_time_ + kUpdateIntervalMs) 114b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org return 0; 115b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 1168084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org last_process_time_ = now; 117b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 1188084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org RemoveOldReports(now, &reports_); 1198084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org max_rtt_ms_ = GetMaxRttMs(&reports_); 1208084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org UpdateAvgRttMs(&reports_, &avg_rtt_ms_); 1218ca8a71de2ab16eaafd9c0e5aac87d28aab490eastefan@webrtc.org 1228084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org // If there is a valid rtt, update all observers with the max rtt. 1238084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org // TODO(asapersson): Consider changing this to report the average rtt. 1248084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org if (max_rtt_ms_ > 0) { 1258ca8a71de2ab16eaafd9c0e5aac87d28aab490eastefan@webrtc.org for (std::list<CallStatsObserver*>::iterator it = observers_.begin(); 1268ca8a71de2ab16eaafd9c0e5aac87d28aab490eastefan@webrtc.org it != observers_.end(); ++it) { 1272328a94ec7ee545a26e8220c5ae157e1b3b5144fstefan (*it)->OnRttUpdate(avg_rtt_ms_, max_rtt_ms_); 1288ca8a71de2ab16eaafd9c0e5aac87d28aab490eastefan@webrtc.org } 129b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org } 130b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org return 0; 131b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 132b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 13316825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint64_t CallStats::avg_rtt_ms() const { 1341ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org CriticalSectionScoped cs(crit_.get()); 1358084f9500f5d28b01638ad396622a0b6c5820701asapersson@webrtc.org return avg_rtt_ms_; 1361ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org} 1371ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org 1381ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.orgRtcpRttStats* CallStats::rtcp_rtt_stats() const { 1391ae1d0c47145f1036c3844a5cd1b536c22565325asapersson@webrtc.org return rtcp_rtt_stats_.get(); 140b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 141b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 142aea96d36e3691de0f95734f6d88bb94474903b34fischman@webrtc.orgvoid CallStats::RegisterStatsObserver(CallStatsObserver* observer) { 143b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 144aea96d36e3691de0f95734f6d88bb94474903b34fischman@webrtc.org for (std::list<CallStatsObserver*>::iterator it = observers_.begin(); 145b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org it != observers_.end(); ++it) { 146b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org if (*it == observer) 147b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org return; 148b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org } 149b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org observers_.push_back(observer); 150b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 151b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 152aea96d36e3691de0f95734f6d88bb94474903b34fischman@webrtc.orgvoid CallStats::DeregisterStatsObserver(CallStatsObserver* observer) { 153b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 154aea96d36e3691de0f95734f6d88bb94474903b34fischman@webrtc.org for (std::list<CallStatsObserver*>::iterator it = observers_.begin(); 155b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org it != observers_.end(); ++it) { 156b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org if (*it == observer) { 157b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org observers_.erase(it); 158b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org return; 159b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org } 160b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org } 161b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 162b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 16316825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgvoid CallStats::OnRttUpdate(int64_t rtt) { 164b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org CriticalSectionScoped cs(crit_.get()); 165d3c944755ec546f46d5bdd84bff359fe6c4639e9Peter Boström reports_.push_back(RttTime(rtt, clock_->TimeInMilliseconds())); 166b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} 167b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org 168b2f474e8bb0385ef25b11fb4b75ca17e1f423a66mflodman@webrtc.org} // namespace webrtc 169