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

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

Issue 2235373004: Probing: Add support for exponential startup probing (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@fix_probing2
Patch Set: Updates 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 #include <utility>
18 18
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
21 #include "webrtc/modules/pacing/paced_sender.h" 21 #include "webrtc/modules/pacing/paced_sender.h"
22 22
23 namespace webrtc { 23 namespace webrtc {
24 24
25 namespace { 25 namespace {
26 26
27 // Inactivity threshold above which probing is restarted. 27 // Inactivity threshold above which probing is restarted.
28 constexpr int kInactivityThresholdMs = 5000; 28 constexpr int kInactivityThresholdMs = 5000;
29 // Number of packets per cluster of probes.
30 constexpr int kPacketsPerCluster = 5;
29 31
30 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) { 32 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) {
31 assert(bitrate_bps > 0); 33 assert(bitrate_bps > 0);
32 // Compute the time delta needed to send packet_size bytes at bitrate_bps 34 // Compute the time delta needed to send packet_size bytes at bitrate_bps
33 // bps. Result is in milliseconds. 35 // bps. Result is in milliseconds.
34 return static_cast<int>((1000ll * packet_size * 8) / bitrate_bps); 36 return static_cast<int>((1000ll * packet_size * 8) / bitrate_bps);
35 } 37 }
36 } // namespace 38 } // namespace
37 39
38 BitrateProber::BitrateProber() 40 BitrateProber::BitrateProber()
39 : probing_state_(ProbingState::kDisabled), 41 : probing_state_(State::kDisabled),
40 packet_size_last_sent_(0), 42 packet_size_last_sent_(0),
41 time_last_probe_sent_ms_(-1), 43 time_last_probe_sent_ms_(-1),
42 next_cluster_id_(0) { 44 next_cluster_id_(0) {
43 SetEnabled(true); 45 SetEnabled(true);
44 } 46 }
45 47
46 void BitrateProber::SetEnabled(bool enable) { 48 void BitrateProber::SetEnabled(bool enable) {
47 if (enable) { 49 if (enable) {
48 if (probing_state_ == ProbingState::kDisabled) { 50 if (probing_state_ == State::kDisabled) {
49 probing_state_ = ProbingState::kInactive; 51 probing_state_ = State::kInactive;
50 LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive"; 52 LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive";
51 } 53 }
52 } else { 54 } else {
53 probing_state_ = ProbingState::kDisabled; 55 probing_state_ = State::kDisabled;
54 LOG(LS_INFO) << "Bandwidth probing disabled"; 56 LOG(LS_INFO) << "Bandwidth probing disabled";
55 } 57 }
56 } 58 }
57 59
58 bool BitrateProber::IsProbing() const { 60 bool BitrateProber::IsProbing() const {
59 return probing_state_ == ProbingState::kActive; 61 return probing_state_ == State::kActive;
60 } 62 }
61 63
62 void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps, 64 bool BitrateProber::InitiateProbing(uint32_t bitrate_bps,
63 size_t packet_size, 65 const int* multipliers,
64 int64_t now_ms) { 66 int multipler_count) {
65 // Don't initialize probing unless we have something large enough to start
66 // probing.
67 if (packet_size < PacedSender::kMinProbePacketSize)
68 return;
69 if (probing_state_ != ProbingState::kInactive)
70 return;
71 // Max number of packets used for probing.
72 const int kMaxNumProbes = 2;
73 const int kPacketsPerProbe = 5;
74 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
75 std::stringstream bitrate_log; 67 std::stringstream bitrate_log;
76 bitrate_log << "Start probing for bandwidth, (bitrate:packets): "; 68 bitrate_log << "Start probing for bandwidth, (bitrate:packets): ";
77 for (int i = 0; i < kMaxNumProbes; ++i) { 69 for (int i = 0; i < multipler_count; ++i) {
78 ProbeCluster cluster; 70 ProbeCluster cluster;
79 // We need one extra to get 5 deltas for the first probe, therefore (i == 0) 71 // We need one extra to get 5 deltas for the first probe, therefore (i == 0)
80 cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0); 72 cluster.max_probe_packets = kPacketsPerCluster + (i == 0 ? 1 : 0);
81 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps; 73 cluster.probe_bitrate_bps = multipliers[i] * bitrate_bps;
82 cluster.id = next_cluster_id_++; 74 cluster.id = next_cluster_id_++;
83 75
84 bitrate_log << "(" << cluster.probe_bitrate_bps << ":" 76 bitrate_log << "(" << cluster.probe_bitrate_bps << ":"
85 << cluster.max_probe_packets << ") "; 77 << cluster.max_probe_packets << ") ";
86 78
87 clusters_.push(cluster); 79 clusters_.push(cluster);
88 } 80 }
89 LOG(LS_INFO) << bitrate_log.str().c_str(); 81 LOG(LS_INFO) << bitrate_log.str().c_str();
90 probing_state_ = ProbingState::kActive; 82 probing_state_ = State::kActive;
83 return true;
91 } 84 }
92 85
93 void BitrateProber::ResetState() { 86 void BitrateProber::ResetState() {
94 time_last_probe_sent_ms_ = -1; 87 time_last_probe_sent_ms_ = -1;
95 packet_size_last_sent_ = 0; 88 packet_size_last_sent_ = 0;
96 clusters_ = std::queue<ProbeCluster>(); 89 clusters_ = std::queue<ProbeCluster>();
97 // If its enabled, reset to inactive. 90 // If its enabled, reset to inactive.
98 if (probing_state_ != ProbingState::kDisabled) 91 if (probing_state_ != State::kDisabled)
99 probing_state_ = ProbingState::kInactive; 92 probing_state_ = State::kInactive;
100 } 93 }
101 94
102 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { 95 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
103 // Probing is not active or probing is already complete. 96 // Probing is not active or probing is already complete.
104 if (probing_state_ != ProbingState::kActive || clusters_.empty()) 97 if (probing_state_ != State::kActive || clusters_.empty())
105 return -1; 98 return -1;
106 // time_last_probe_sent_ms_ of -1 indicates no probes have yet been sent. 99 // time_last_probe_sent_ms_ of -1 indicates no probes have yet been sent.
107 int64_t elapsed_time_ms; 100 int64_t elapsed_time_ms;
108 if (time_last_probe_sent_ms_ == -1) { 101 if (time_last_probe_sent_ms_ == -1) {
109 elapsed_time_ms = 0; 102 elapsed_time_ms = 0;
110 } else { 103 } else {
111 elapsed_time_ms = now_ms - time_last_probe_sent_ms_; 104 elapsed_time_ms = now_ms - time_last_probe_sent_ms_;
112 } 105 }
113 // If no probes have been sent for a while, abort current probing and 106 // If no probes have been sent for a while, abort current probing and
114 // reset. 107 // reset.
115 if (elapsed_time_ms > kInactivityThresholdMs) { 108 if (elapsed_time_ms > kInactivityThresholdMs) {
116 ResetState(); 109 ResetState();
117 return -1; 110 return -1;
118 } 111 }
119 // We will send the first probe packet immediately if no packet has been 112 // We will send the first probe packet immediately if no packet has been
120 // sent before. 113 // sent before.
121 int time_until_probe_ms = 0; 114 int time_until_probe_ms = 0;
122 if (packet_size_last_sent_ != 0 && probing_state_ == ProbingState::kActive) { 115 if (packet_size_last_sent_ != 0 && probing_state_ == State::kActive) {
123 int next_delta_ms = ComputeDeltaFromBitrate( 116 int next_delta_ms = ComputeDeltaFromBitrate(
124 packet_size_last_sent_, clusters_.front().probe_bitrate_bps); 117 packet_size_last_sent_, clusters_.front().probe_bitrate_bps);
125 time_until_probe_ms = next_delta_ms - elapsed_time_ms; 118 time_until_probe_ms = next_delta_ms - elapsed_time_ms;
126 // There is no point in trying to probe with less than 1 ms between packets 119 // There is no point in trying to probe with less than 1 ms between packets
127 // as it essentially means trying to probe at infinite bandwidth. 120 // as it essentially means trying to probe at infinite bandwidth.
128 const int kMinProbeDeltaMs = 1; 121 const int kMinProbeDeltaMs = 1;
129 // If we have waited more than 3 ms for a new packet to probe with we will 122 // If we have waited more than 3 ms for a new packet to probe with we will
130 // consider this probing session over. 123 // consider this probing session over.
131 const int kMaxProbeDelayMs = 3; 124 const int kMaxProbeDelayMs = 3;
132 if (next_delta_ms < kMinProbeDeltaMs || 125 if (next_delta_ms < kMinProbeDeltaMs ||
133 time_until_probe_ms < -kMaxProbeDelayMs) { 126 time_until_probe_ms < -kMaxProbeDelayMs) {
134 probing_state_ = ProbingState::kSuspended; 127 probing_state_ = State::kComplete;
135 LOG(LS_INFO) << "Delta too small or missed probing accurately, suspend"; 128 LOG(LS_INFO) << "Delta too small or missed probing accurately, suspend";
136 time_until_probe_ms = 0; 129 time_until_probe_ms = 0;
137 } 130 }
138 } 131 }
139 return std::max(time_until_probe_ms, 0); 132 return std::max(time_until_probe_ms, 0);
140 } 133 }
141 134
142 int BitrateProber::CurrentClusterId() const { 135 int BitrateProber::CurrentClusterId() const {
143 RTC_DCHECK(!clusters_.empty()); 136 RTC_DCHECK(!clusters_.empty());
144 RTC_DCHECK(ProbingState::kActive == probing_state_); 137 RTC_DCHECK(State::kActive == probing_state_);
145 return clusters_.front().id; 138 return clusters_.front().id;
146 } 139 }
147 140
148 size_t BitrateProber::RecommendedPacketSize() const { 141 size_t BitrateProber::RecommendedPacketSize() const {
149 return packet_size_last_sent_; 142 return packet_size_last_sent_;
150 } 143 }
151 144
152 void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) { 145 BitrateProber::State BitrateProber::PacketSent(int64_t now_ms,
146 size_t packet_size) {
153 assert(packet_size > 0); 147 assert(packet_size > 0);
148 RTC_DCHECK(probing_state_ == State::kActive);
stefan-webrtc 2016/08/16 11:27:04 Isn't it good to notify the prober about recent pa
Irfan 2016/08/16 18:12:47 We initiate probing only when there is an incoming
149
154 if (packet_size < PacedSender::kMinProbePacketSize) 150 if (packet_size < PacedSender::kMinProbePacketSize)
155 return; 151 return probing_state_;
156 packet_size_last_sent_ = packet_size; 152 packet_size_last_sent_ = packet_size;
157 if (probing_state_ != ProbingState::kActive)
158 return;
159 time_last_probe_sent_ms_ = now_ms; 153 time_last_probe_sent_ms_ = now_ms;
160 if (!clusters_.empty()) { 154 if (!clusters_.empty()) {
161 ProbeCluster* cluster = &clusters_.front(); 155 ProbeCluster* cluster = &clusters_.front();
162 ++cluster->sent_probe_packets; 156 ++cluster->sent_probe_packets;
163 if (cluster->sent_probe_packets == cluster->max_probe_packets) 157 if (cluster->sent_probe_packets == cluster->max_probe_packets)
164 clusters_.pop(); 158 clusters_.pop();
165 if (clusters_.empty()) 159 if (clusters_.empty())
166 probing_state_ = ProbingState::kSuspended; 160 probing_state_ = State::kComplete;
167 } 161 }
162 return probing_state_;
168 } 163 }
169 } // namespace webrtc 164 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698