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