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