blob: 05385c35eabfa8567d29943cd88bb72426b449d4 [file] [log] [blame]
mflodman@webrtc.orge2967832012-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.org3f45c2e2013-08-05 16:22:53 +000013#include <assert.h>
mflodman@webrtc.orge2967832012-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"
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000018
19namespace webrtc {
20
21// A rtt report is considered valid for this long.
22const int kRttTimeoutMs = 1500;
23// Time interval for updating the observers.
24const int kUpdateIntervalMs = 1000;
25
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +000026class RtcpObserver : public RtcpRttStats {
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000027 public:
28 explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
29 virtual ~RtcpObserver() {}
30
31 virtual void OnRttUpdate(uint32_t rtt) {
32 owner_->OnRttUpdate(rtt);
33 }
34
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +000035 virtual uint32_t LastProcessedRtt() const {
36 return owner_->last_processed_rtt_ms();
37 }
38
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000039 private:
40 CallStats* owner_;
41
42 DISALLOW_COPY_AND_ASSIGN(RtcpObserver);
43};
44
45CallStats::CallStats()
46 : crit_(CriticalSectionWrapper::CreateCriticalSection()),
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +000047 rtcp_rtt_stats_(new RtcpObserver(this)),
48 last_process_time_(TickTime::MillisecondTimestamp()),
49 last_processed_rtt_ms_(0) {
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000050}
51
52CallStats::~CallStats() {
53 assert(observers_.empty());
54}
55
56int32_t CallStats::TimeUntilNextProcess() {
57 return last_process_time_ + kUpdateIntervalMs -
58 TickTime::MillisecondTimestamp();
59}
60
61int32_t CallStats::Process() {
62 CriticalSectionScoped cs(crit_.get());
63 if (TickTime::MillisecondTimestamp() < last_process_time_ + kUpdateIntervalMs)
64 return 0;
65
66 // Remove invalid, as in too old, rtt values.
67 int64_t time_now = TickTime::MillisecondTimestamp();
68 while (!reports_.empty() && reports_.front().time + kRttTimeoutMs <
69 time_now) {
70 reports_.pop_front();
71 }
72
73 // Find the max stored RTT.
74 uint32_t max_rtt = 0;
75 for (std::list<RttTime>::const_iterator it = reports_.begin();
76 it != reports_.end(); ++it) {
77 if (it->rtt > max_rtt)
78 max_rtt = it->rtt;
79 }
stefan@webrtc.orgd430f322013-04-23 16:48:32 +000080
stefan@webrtc.org27881072013-04-23 15:58:23 +000081 // If there is a valid rtt, update all observers.
stefan@webrtc.orgd430f322013-04-23 16:48:32 +000082 if (max_rtt > 0) {
83 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
84 it != observers_.end(); ++it) {
85 (*it)->OnRttUpdate(max_rtt);
86 }
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000087 }
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +000088 last_processed_rtt_ms_ = max_rtt;
mflodman@webrtc.orge2967832012-11-16 13:57:26 +000089 last_process_time_ = time_now;
90 return 0;
91}
92
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +000093uint32_t CallStats::last_processed_rtt_ms() const {
94 CriticalSectionScoped cs(crit_.get());
95 return last_processed_rtt_ms_;
96}
97
98RtcpRttStats* CallStats::rtcp_rtt_stats() const {
99 return rtcp_rtt_stats_.get();
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000100}
101
fischman@webrtc.org0329e592013-02-19 22:09:36 +0000102void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000103 CriticalSectionScoped cs(crit_.get());
fischman@webrtc.org0329e592013-02-19 22:09:36 +0000104 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000105 it != observers_.end(); ++it) {
106 if (*it == observer)
107 return;
108 }
109 observers_.push_back(observer);
110}
111
fischman@webrtc.org0329e592013-02-19 22:09:36 +0000112void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000113 CriticalSectionScoped cs(crit_.get());
fischman@webrtc.org0329e592013-02-19 22:09:36 +0000114 for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000115 it != observers_.end(); ++it) {
116 if (*it == observer) {
117 observers_.erase(it);
118 return;
119 }
120 }
121}
122
123void CallStats::OnRttUpdate(uint32_t rtt) {
124 CriticalSectionScoped cs(crit_.get());
125 int64_t time_now = TickTime::MillisecondTimestamp();
126 reports_.push_back(RttTime(rtt, time_now));
mflodman@webrtc.orge2967832012-11-16 13:57:26 +0000127}
128
129} // namespace webrtc