blob: a79a7d2fb5100fdb72cf53181ce85c98a39eafd9 [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
11#include "webrtc/video_engine/call_stats.h"
12
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000014
15#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
16#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17#include "webrtc/system_wrappers/interface/tick_util.h"
18#include "webrtc/system_wrappers/interface/trace.h"
19
20namespace webrtc {
21
22// A rtt report is considered valid for this long.
23const int kRttTimeoutMs = 1500;
24// Time interval for updating the observers.
25const int kUpdateIntervalMs = 1000;
26
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000027class RtcpObserver : public RtcpRttStats {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000028 public:
29 explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
30 virtual ~RtcpObserver() {}
31
32 virtual void OnRttUpdate(uint32_t rtt) {
33 owner_->OnRttUpdate(rtt);
34 }
35
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000036 virtual uint32_t LastProcessedRtt() const {
37 return owner_->last_processed_rtt_ms();
38 }
39
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000040 private:
41 CallStats* owner_;
42
43 DISALLOW_COPY_AND_ASSIGN(RtcpObserver);
44};
45
46CallStats::CallStats()
47 : crit_(CriticalSectionWrapper::CreateCriticalSection()),
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000048 rtcp_rtt_stats_(new RtcpObserver(this)),
49 last_process_time_(TickTime::MillisecondTimestamp()),
50 last_processed_rtt_ms_(0) {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000051}
52
53CallStats::~CallStats() {
54 assert(observers_.empty());
55}
56
57int32_t CallStats::TimeUntilNextProcess() {
58 return last_process_time_ + kUpdateIntervalMs -
59 TickTime::MillisecondTimestamp();
60}
61
62int32_t CallStats::Process() {
63 CriticalSectionScoped cs(crit_.get());
64 if (TickTime::MillisecondTimestamp() < last_process_time_ + kUpdateIntervalMs)
65 return 0;
66
67 // Remove invalid, as in too old, rtt values.
68 int64_t time_now = TickTime::MillisecondTimestamp();
69 while (!reports_.empty() && reports_.front().time + kRttTimeoutMs <
70 time_now) {
71 reports_.pop_front();
72 }
73
74 // Find the max stored RTT.
75 uint32_t max_rtt = 0;
76 for (std::list<RttTime>::const_iterator it = reports_.begin();
77 it != reports_.end(); ++it) {
78 if (it->rtt > max_rtt)
79 max_rtt = it->rtt;
80 }
stefan@webrtc.org8ca8a712013-04-23 16:48:32 +000081
stefan@webrtc.orgccd4b2a2013-04-23 15:58:23 +000082 // If there is a valid rtt, update all observers.
stefan@webrtc.org8ca8a712013-04-23 16:48:32 +000083 if (max_rtt > 0) {
84 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
85 it != observers_.end(); ++it) {
86 (*it)->OnRttUpdate(max_rtt);
87 }
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000088 }
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000089 last_processed_rtt_ms_ = max_rtt;
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +000090 last_process_time_ = time_now;
91 return 0;
92}
93
asapersson@webrtc.org1ae1d0c2013-11-20 12:46:11 +000094uint32_t CallStats::last_processed_rtt_ms() const {
95 CriticalSectionScoped cs(crit_.get());
96 return last_processed_rtt_ms_;
97}
98
99RtcpRttStats* CallStats::rtcp_rtt_stats() const {
100 return rtcp_rtt_stats_.get();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000101}
102
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000103void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000104 CriticalSectionScoped cs(crit_.get());
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000105 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000106 it != observers_.end(); ++it) {
107 if (*it == observer)
108 return;
109 }
110 observers_.push_back(observer);
111}
112
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000113void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000114 CriticalSectionScoped cs(crit_.get());
fischman@webrtc.orgaea96d32013-02-19 22:09:36 +0000115 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000116 it != observers_.end(); ++it) {
117 if (*it == observer) {
118 observers_.erase(it);
119 return;
120 }
121 }
122}
123
124void CallStats::OnRttUpdate(uint32_t rtt) {
125 CriticalSectionScoped cs(crit_.get());
126 int64_t time_now = TickTime::MillisecondTimestamp();
127 reports_.push_back(RttTime(rtt, time_now));
mflodman@webrtc.orgb2f474e2012-11-16 13:57:26 +0000128}
129
130} // namespace webrtc