1 /*
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/modules/rtp_rtcp/source/bitrate.h"
12
13 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
14 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
15
16 namespace webrtc {
17
Bitrate(Clock * clock,Observer * observer)18 Bitrate::Bitrate(Clock* clock, Observer* observer)
19 : clock_(clock),
20 crit_(CriticalSectionWrapper::CreateCriticalSection()),
21 packet_rate_(0),
22 bitrate_(0),
23 bitrate_next_idx_(0),
24 time_last_rate_update_(0),
25 bytes_count_(0),
26 packet_count_(0),
27 observer_(observer) {
28 memset(packet_rate_array_, 0, sizeof(packet_rate_array_));
29 memset(bitrate_diff_ms_, 0, sizeof(bitrate_diff_ms_));
30 memset(bitrate_array_, 0, sizeof(bitrate_array_));
31 }
32
~Bitrate()33 Bitrate::~Bitrate() {}
34
Update(const size_t bytes)35 void Bitrate::Update(const size_t bytes) {
36 CriticalSectionScoped cs(crit_.get());
37 bytes_count_ += bytes;
38 packet_count_++;
39 }
40
PacketRate() const41 uint32_t Bitrate::PacketRate() const {
42 CriticalSectionScoped cs(crit_.get());
43 return packet_rate_;
44 }
45
BitrateLast() const46 uint32_t Bitrate::BitrateLast() const {
47 CriticalSectionScoped cs(crit_.get());
48 return bitrate_;
49 }
50
BitrateNow() const51 uint32_t Bitrate::BitrateNow() const {
52 CriticalSectionScoped cs(crit_.get());
53 int64_t now = clock_->TimeInMilliseconds();
54 int64_t diff_ms = now - time_last_rate_update_;
55
56 if (diff_ms > 10000) { // 10 seconds.
57 // Too high difference, ignore.
58 return bitrate_;
59 }
60 int64_t bits_since_last_rate_update = 8 * bytes_count_ * 1000;
61
62 // We have to consider the time when the measurement was done:
63 // ((bits/sec * sec) + (bits)) / sec.
64 int64_t bitrate = (static_cast<uint64_t>(bitrate_) * 1000 +
65 bits_since_last_rate_update) / (1000 + diff_ms);
66 return static_cast<uint32_t>(bitrate);
67 }
68
time_last_rate_update() const69 int64_t Bitrate::time_last_rate_update() const {
70 CriticalSectionScoped cs(crit_.get());
71 return time_last_rate_update_;
72 }
73
74 // Triggered by timer.
Process()75 void Bitrate::Process() {
76 BitrateStatistics stats;
77 {
78 CriticalSectionScoped cs(crit_.get());
79 int64_t now = clock_->CurrentNtpInMilliseconds();
80 int64_t diff_ms = now - time_last_rate_update_;
81
82 if (diff_ms < 100) {
83 // Not enough data, wait...
84 return;
85 }
86 if (diff_ms > 10000) { // 10 seconds.
87 // Too high difference, ignore.
88 time_last_rate_update_ = now;
89 bytes_count_ = 0;
90 packet_count_ = 0;
91 return;
92 }
93 packet_rate_array_[bitrate_next_idx_] = (packet_count_ * 1000) / diff_ms;
94 bitrate_array_[bitrate_next_idx_] = 8 * ((bytes_count_ * 1000) / diff_ms);
95 bitrate_diff_ms_[bitrate_next_idx_] = diff_ms;
96 bitrate_next_idx_++;
97 if (bitrate_next_idx_ >= 10) {
98 bitrate_next_idx_ = 0;
99 }
100 int64_t sum_diffMS = 0;
101 int64_t sum_bitrateMS = 0;
102 int64_t sum_packetrateMS = 0;
103 for (int i = 0; i < 10; i++) {
104 sum_diffMS += bitrate_diff_ms_[i];
105 sum_bitrateMS += bitrate_array_[i] * bitrate_diff_ms_[i];
106 sum_packetrateMS += packet_rate_array_[i] * bitrate_diff_ms_[i];
107 }
108 time_last_rate_update_ = now;
109 bytes_count_ = 0;
110 packet_count_ = 0;
111 packet_rate_ = static_cast<uint32_t>(sum_packetrateMS / sum_diffMS);
112 bitrate_ = static_cast<uint32_t>(sum_bitrateMS / sum_diffMS);
113
114 stats.bitrate_bps = bitrate_;
115 stats.packet_rate = packet_rate_;
116 stats.timestamp_ms = now;
117 }
118
119 if (observer_)
120 observer_->BitrateUpdated(stats);
121 }
122
123 } // namespace webrtc
124