Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(906)

Side by Side Diff: webrtc/modules/pacing/bitrate_prober.cc

Issue 2182603002: Bitrate prober and paced sender improvements (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Bitrate prober and paced sender improvements Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/pacing/bitrate_prober.h" 11 #include "webrtc/modules/pacing/bitrate_prober.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <algorithm> 14 #include <algorithm>
15 #include <limits> 15 #include <limits>
16 #include <sstream> 16 #include <sstream>
17 #include <utility>
17 18
18 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
19 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
20 #include "webrtc/modules/pacing/paced_sender.h" 21 #include "webrtc/modules/pacing/paced_sender.h"
21 22
22 namespace webrtc { 23 namespace webrtc {
23 24
24 namespace { 25 namespace {
26
27 // Inactivity threshold above which probing is restarted.
28 static constexpr int kInactivityThresholdMs = 5000;
philipel 2016/08/01 11:35:05 No need for static since you are using an anonymou
Irfan 2016/08/01 18:29:46 Done.
29
25 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) { 30 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) {
26 assert(bitrate_bps > 0); 31 assert(bitrate_bps > 0);
27 // Compute the time delta needed to send packet_size bytes at bitrate_bps 32 // Compute the time delta needed to send packet_size bytes at bitrate_bps
28 // bps. Result is in milliseconds. 33 // bps. Result is in milliseconds.
29 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll / 34 return static_cast<int>((1000ll * packet_size * 8) / bitrate_bps);
30 bitrate_bps);
31 } 35 }
32 } // namespace 36 } // namespace
33 37
34 BitrateProber::BitrateProber() 38 BitrateProber::BitrateProber()
35 : probing_state_(kDisabled), 39 : probing_state_(ProbingState::kDisabled),
philipel 2016/08/01 11:35:05 ProbingState::kDisabled -> kDisabled Or is there a
Irfan 2016/08/01 18:29:46 Yes, this is now a scoped enum.
36 packet_size_last_send_(0), 40 packet_size_last_sent_(0),
37 time_last_send_ms_(-1), 41 time_last_probe_sent_ms_(-1),
38 next_cluster_id_(0) {} 42 next_cluster_id_(0) {
43 SetEnabled(true);
44 }
39 45
40 void BitrateProber::SetEnabled(bool enable) { 46 void BitrateProber::SetEnabled(bool enable) {
41 if (enable) { 47 if (enable) {
42 if (probing_state_ == kDisabled) { 48 if (probing_state_ == ProbingState::kDisabled) {
43 probing_state_ = kAllowedToProbe; 49 probing_state_ = ProbingState::kInactive;
44 LOG(LS_INFO) << "Initial bandwidth probing enabled"; 50 LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive";
45 } 51 }
46 } else { 52 } else {
47 probing_state_ = kDisabled; 53 probing_state_ = ProbingState::kDisabled;
48 LOG(LS_INFO) << "Initial bandwidth probing disabled"; 54 LOG(LS_INFO) << "Bandwidth probing disabled";
49 } 55 }
50 } 56 }
51 57
52 bool BitrateProber::IsProbing() const { 58 bool BitrateProber::IsProbing() const {
53 return probing_state_ == kProbing; 59 return probing_state_ == ProbingState::kActive;
54 } 60 }
55 61
56 void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps, 62 void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps,
57 size_t packet_size, 63 size_t packet_size,
58 int64_t now_ms) { 64 int64_t now_ms) {
59 // Don't initialize probing unless we have something large enough to start 65 // Don't initialize probing unless we have something large enough to start
60 // probing. 66 // probing.
61 if (packet_size < PacedSender::kMinProbePacketSize) 67 if (packet_size < PacedSender::kMinProbePacketSize)
62 return; 68 return;
63 if (probing_state_ != kAllowedToProbe) 69 if (probing_state_ != ProbingState::kInactive)
64 return; 70 return;
65 // Max number of packets used for probing. 71 // Max number of packets used for probing.
66 const int kMaxNumProbes = 2; 72 const int kMaxNumProbes = 2;
67 const int kPacketsPerProbe = 5; 73 const int kPacketsPerProbe = 5;
68 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6}; 74 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
69 std::stringstream bitrate_log; 75 std::stringstream bitrate_log;
70 bitrate_log << "Start probing for bandwidth, (bitrate:packets): "; 76 bitrate_log << "Start probing for bandwidth, (bitrate:packets): ";
71 for (int i = 0; i < kMaxNumProbes; ++i) { 77 for (int i = 0; i < kMaxNumProbes; ++i) {
72 ProbeCluster cluster; 78 ProbeCluster cluster;
73 // We need one extra to get 5 deltas for the first probe, therefore (i == 0) 79 // We need one extra to get 5 deltas for the first probe, therefore (i == 0)
74 cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0); 80 cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0);
75 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps; 81 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps;
76 cluster.id = next_cluster_id_++; 82 cluster.id = next_cluster_id_++;
77 83
78 bitrate_log << "(" << cluster.probe_bitrate_bps << ":" 84 bitrate_log << "(" << cluster.probe_bitrate_bps << ":"
79 << cluster.max_probe_packets << ") "; 85 << cluster.max_probe_packets << ") ";
80 86
81 clusters_.push(cluster); 87 clusters_.push(cluster);
82 } 88 }
83 LOG(LS_INFO) << bitrate_log.str().c_str(); 89 LOG(LS_INFO) << bitrate_log.str().c_str();
84 // Set last send time to current time so TimeUntilNextProbe doesn't short 90 probing_state_ = ProbingState::kActive;
85 // circuit due to inactivity. 91 }
86 time_last_send_ms_ = now_ms; 92
87 probing_state_ = kProbing; 93 void BitrateProber::ResetState() {
94 std::queue<ProbeCluster> empty_cluster_;
stefan-webrtc 2016/07/29 07:12:07 No _ at the end of this variable name.
Irfan 2016/08/01 18:29:46 Done.
95 time_last_probe_sent_ms_ = -1;
96 packet_size_last_sent_ = 0;
97 std::swap(clusters_, empty_cluster_);
stefan-webrtc 2016/07/29 07:12:07 Is this more efficient than doing: clusters_ = std
Irfan 2016/08/01 18:29:46 Either works mostly the same. I switched it.
98 // If its enabled, reset to inactive.
99 if (probing_state_ != ProbingState::kDisabled)
100 probing_state_ = ProbingState::kInactive;
88 } 101 }
89 102
90 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { 103 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
91 if (probing_state_ != kDisabled && clusters_.empty()) { 104 // Probing is not active or probing is already complete.
92 probing_state_ = kWait; 105 if (probing_state_ != ProbingState::kActive || clusters_.empty())
106 return -1;
107 // time_last_probe_sent_ms_ of -1 indicates no probes have yet been sent.
108 int64_t elapsed_time_ms;
109 if (time_last_probe_sent_ms_ == -1) {
110 elapsed_time_ms = 0;
111 } else {
112 elapsed_time_ms = now_ms - time_last_probe_sent_ms_;
93 } 113 }
94 114 // If no probes have been sent for a while, abort current probing and
95 if (clusters_.empty() || time_last_send_ms_ == -1) { 115 // reset.
96 // No probe started, probe finished, or too long since last probe packet. 116 if (elapsed_time_ms > kInactivityThresholdMs) {
97 return -1; 117 ResetState();
98 }
99 int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
100 // If no packets have been sent for n milliseconds, temporarily deactivate to
101 // not keep spinning.
102 static const int kInactiveSendDeltaMs = 5000;
103 if (elapsed_time_ms > kInactiveSendDeltaMs) {
104 time_last_send_ms_ = -1;
105 probing_state_ = kAllowedToProbe;
106 return -1; 118 return -1;
107 } 119 }
108 // We will send the first probe packet immediately if no packet has been 120 // We will send the first probe packet immediately if no packet has been
109 // sent before. 121 // sent before.
110 int time_until_probe_ms = 0; 122 int time_until_probe_ms = 0;
111 if (packet_size_last_send_ != 0 && probing_state_ == kProbing) { 123 if (packet_size_last_sent_ != 0 && probing_state_ == ProbingState::kActive) {
112 int next_delta_ms = ComputeDeltaFromBitrate( 124 int next_delta_ms = ComputeDeltaFromBitrate(
113 packet_size_last_send_, clusters_.front().probe_bitrate_bps); 125 packet_size_last_sent_, clusters_.front().probe_bitrate_bps);
114 time_until_probe_ms = next_delta_ms - elapsed_time_ms; 126 time_until_probe_ms = next_delta_ms - elapsed_time_ms;
115 // There is no point in trying to probe with less than 1 ms between packets 127 // There is no point in trying to probe with less than 1 ms between packets
116 // as it essentially means trying to probe at infinite bandwidth. 128 // as it essentially means trying to probe at infinite bandwidth.
117 const int kMinProbeDeltaMs = 1; 129 const int kMinProbeDeltaMs = 1;
118 // If we have waited more than 3 ms for a new packet to probe with we will 130 // If we have waited more than 3 ms for a new packet to probe with we will
119 // consider this probing session over. 131 // consider this probing session over.
120 const int kMaxProbeDelayMs = 3; 132 const int kMaxProbeDelayMs = 3;
121 if (next_delta_ms < kMinProbeDeltaMs || 133 if (next_delta_ms < kMinProbeDeltaMs ||
122 time_until_probe_ms < -kMaxProbeDelayMs) { 134 time_until_probe_ms < -kMaxProbeDelayMs) {
123 // We currently disable probing after the first probe, as we only want 135 probing_state_ = ProbingState::kSuspended;
124 // to probe at the beginning of a connection. We should set this to 136 LOG(LS_INFO) << "Delta too small or missed probing accurately, suspend";
125 // kWait if we later want to probe periodically.
126 probing_state_ = kWait;
127 LOG(LS_INFO) << "Next delta too small, stop probing.";
128 time_until_probe_ms = 0; 137 time_until_probe_ms = 0;
129 } 138 }
130 } 139 }
131 return std::max(time_until_probe_ms, 0); 140 return std::max(time_until_probe_ms, 0);
132 } 141 }
133 142
134 int BitrateProber::CurrentClusterId() const { 143 int BitrateProber::CurrentClusterId() const {
135 RTC_DCHECK(!clusters_.empty()); 144 RTC_DCHECK(!clusters_.empty());
136 RTC_DCHECK_EQ(kProbing, probing_state_); 145 RTC_DCHECK(ProbingState::kActive == probing_state_);
philipel 2016/08/01 11:35:05 Why change from RTC_DCHECK_EQ?
Irfan 2016/08/01 18:29:46 RTC_DCHECK_EQ does not work well with scoped enums
137 return clusters_.front().id; 146 return clusters_.front().id;
138 } 147 }
139 148
140 size_t BitrateProber::RecommendedPacketSize() const { 149 size_t BitrateProber::RecommendedPacketSize() const {
141 return packet_size_last_send_; 150 return packet_size_last_sent_;
142 } 151 }
143 152
144 void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) { 153 void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
145 assert(packet_size > 0); 154 assert(packet_size > 0);
146 if (packet_size < PacedSender::kMinProbePacketSize) 155 if (packet_size < PacedSender::kMinProbePacketSize)
147 return; 156 return;
148 packet_size_last_send_ = packet_size; 157 packet_size_last_sent_ = packet_size;
149 time_last_send_ms_ = now_ms; 158 if (probing_state_ != ProbingState::kActive)
150 if (probing_state_ != kProbing)
151 return; 159 return;
160 time_last_probe_sent_ms_ = now_ms;
152 if (!clusters_.empty()) { 161 if (!clusters_.empty()) {
153 ProbeCluster* cluster = &clusters_.front(); 162 ProbeCluster* cluster = &clusters_.front();
154 ++cluster->sent_probe_packets; 163 ++cluster->sent_probe_packets;
155 if (cluster->sent_probe_packets == cluster->max_probe_packets) 164 if (cluster->sent_probe_packets == cluster->max_probe_packets)
156 clusters_.pop(); 165 clusters_.pop();
157 if (clusters_.empty()) 166 if (clusters_.empty())
158 probing_state_ = kWait; 167 probing_state_ = ProbingState::kSuspended;
159 } 168 }
160 } 169 }
161 } // namespace webrtc 170 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698