1e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org/*
2e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *
4e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  Use of this source code is governed by a BSD-style license
5e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  that can be found in the LICENSE file in the root of the source
6e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  tree. An additional intellectual property rights grant can be found
7e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  in the file PATENTS.  All contributing project authors may
8e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org */
10e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
11e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org#include "webrtc/video_engine/call_stats.h"
12e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>
14e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
15e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
16e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
18e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
19e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgnamespace webrtc {
20e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
21e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org// A rtt report is considered valid for this long.
22e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgconst int kRttTimeoutMs = 1500;
23e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org// Time interval for updating the observers.
24e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgconst int kUpdateIntervalMs = 1000;
25e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
26c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgclass RtcpObserver : public RtcpRttStats {
27e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org public:
28e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
29e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  virtual ~RtcpObserver() {}
30e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
31e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  virtual void OnRttUpdate(uint32_t rtt) {
32e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    owner_->OnRttUpdate(rtt);
33e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
34e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
35c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  virtual uint32_t LastProcessedRtt() const {
36c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org    return owner_->last_processed_rtt_ms();
37c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  }
38c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org
39e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org private:
40e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  CallStats* owner_;
41e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
42e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  DISALLOW_COPY_AND_ASSIGN(RtcpObserver);
43e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org};
44e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
45e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgCallStats::CallStats()
46e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    : crit_(CriticalSectionWrapper::CreateCriticalSection()),
47c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org      rtcp_rtt_stats_(new RtcpObserver(this)),
48c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org      last_process_time_(TickTime::MillisecondTimestamp()),
49c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org      last_processed_rtt_ms_(0) {
50e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
51e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
52e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgCallStats::~CallStats() {
53e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  assert(observers_.empty());
54e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
55e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
56e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgint32_t CallStats::TimeUntilNextProcess() {
57e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  return last_process_time_ + kUpdateIntervalMs -
58e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org      TickTime::MillisecondTimestamp();
59e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
60e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
61e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgint32_t CallStats::Process() {
62e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  CriticalSectionScoped cs(crit_.get());
63e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  if (TickTime::MillisecondTimestamp() < last_process_time_ + kUpdateIntervalMs)
64e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    return 0;
65e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
66e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  // Remove invalid, as in too old, rtt values.
67e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  int64_t time_now = TickTime::MillisecondTimestamp();
68e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  while (!reports_.empty() && reports_.front().time + kRttTimeoutMs <
69e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org         time_now) {
70e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    reports_.pop_front();
71e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
72e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
73e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  // Find the max stored RTT.
74e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  uint32_t max_rtt = 0;
75e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  for (std::list<RttTime>::const_iterator it = reports_.begin();
76e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org       it != reports_.end(); ++it) {
77e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    if (it->rtt > max_rtt)
78e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org      max_rtt = it->rtt;
79e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
80d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org
8127881074fb7affae4d4c3e0def3a01c792b75d1dstefan@webrtc.org  // If there is a valid rtt, update all observers.
82d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org  if (max_rtt > 0) {
83d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org    for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
84d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org         it != observers_.end(); ++it) {
85d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org      (*it)->OnRttUpdate(max_rtt);
86d430f32c82239970bc7130bdb3fd8ba3ed2dde2fstefan@webrtc.org    }
87e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
88c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  last_processed_rtt_ms_ = max_rtt;
89e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  last_process_time_ = time_now;
90e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  return 0;
91e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
92e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
93c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orguint32_t CallStats::last_processed_rtt_ms() const {
94c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  CriticalSectionScoped cs(crit_.get());
95c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  return last_processed_rtt_ms_;
96c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org}
97c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org
98c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgRtcpRttStats* CallStats::rtcp_rtt_stats() const {
99c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.org  return rtcp_rtt_stats_.get();
100e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
101e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
1020329e591cd17957836fd295ae9b31f7d3a73e5e8fischman@webrtc.orgvoid CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
103e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  CriticalSectionScoped cs(crit_.get());
1040329e591cd17957836fd295ae9b31f7d3a73e5e8fischman@webrtc.org  for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
105e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org       it != observers_.end(); ++it) {
106e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    if (*it == observer)
107e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org      return;
108e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
109e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  observers_.push_back(observer);
110e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
111e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
1120329e591cd17957836fd295ae9b31f7d3a73e5e8fischman@webrtc.orgvoid CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
113e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  CriticalSectionScoped cs(crit_.get());
1140329e591cd17957836fd295ae9b31f7d3a73e5e8fischman@webrtc.org  for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
115e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org       it != observers_.end(); ++it) {
116e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    if (*it == observer) {
117e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org      observers_.erase(it);
118e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org      return;
119e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org    }
120e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  }
121e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
122e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
123e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.orgvoid CallStats::OnRttUpdate(uint32_t rtt) {
124e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  CriticalSectionScoped cs(crit_.get());
125e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  int64_t time_now = TickTime::MillisecondTimestamp();
126e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org  reports_.push_back(RttTime(rtt, time_now));
127e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}
128e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org
129e296783ae1fd7fa8a52582c8bb63a570e625532amflodman@webrtc.org}  // namespace webrtc
130