OLD | NEW |
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 | 17 |
| 18 #include "webrtc/base/checks.h" |
18 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
19 #include "webrtc/modules/pacing/paced_sender.h" | 20 #include "webrtc/modules/pacing/paced_sender.h" |
20 | 21 |
21 namespace webrtc { | 22 namespace webrtc { |
22 | 23 |
23 namespace { | 24 namespace { |
24 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) { | 25 int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) { |
25 assert(bitrate_bps > 0); | 26 assert(bitrate_bps > 0); |
26 // Compute the time delta needed to send packet_size bytes at bitrate_bps | 27 // Compute the time delta needed to send packet_size bytes at bitrate_bps |
27 // bps. Result is in milliseconds. | 28 // bps. Result is in milliseconds. |
28 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll / | 29 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll / |
29 bitrate_bps); | 30 bitrate_bps); |
30 } | 31 } |
31 } // namespace | 32 } // namespace |
32 | 33 |
33 BitrateProber::BitrateProber() | 34 BitrateProber::BitrateProber() |
34 : probing_state_(kDisabled), | 35 : probing_state_(kDisabled), |
35 packet_size_last_send_(0), | 36 packet_size_last_send_(0), |
36 time_last_send_ms_(-1) { | 37 time_last_send_ms_(-1), |
37 } | 38 cluster_id_(0) {} |
38 | 39 |
39 void BitrateProber::SetEnabled(bool enable) { | 40 void BitrateProber::SetEnabled(bool enable) { |
40 if (enable) { | 41 if (enable) { |
41 if (probing_state_ == kDisabled) { | 42 if (probing_state_ == kDisabled) { |
42 probing_state_ = kAllowedToProbe; | 43 probing_state_ = kAllowedToProbe; |
43 LOG(LS_INFO) << "Initial bandwidth probing enabled"; | 44 LOG(LS_INFO) << "Initial bandwidth probing enabled"; |
44 } | 45 } |
45 } else { | 46 } else { |
46 probing_state_ = kDisabled; | 47 probing_state_ = kDisabled; |
47 LOG(LS_INFO) << "Initial bandwidth probing disabled"; | 48 LOG(LS_INFO) << "Initial bandwidth probing disabled"; |
48 } | 49 } |
49 } | 50 } |
50 | 51 |
51 bool BitrateProber::IsProbing() const { | 52 bool BitrateProber::IsProbing() const { |
52 return probing_state_ == kProbing; | 53 return probing_state_ == kProbing; |
53 } | 54 } |
54 | 55 |
55 void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps, | 56 void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps, |
56 size_t packet_size, | 57 size_t packet_size, |
57 int64_t now_ms) { | 58 int64_t now_ms) { |
58 // Don't initialize probing unless we have something large enough to start | 59 // Don't initialize probing unless we have something large enough to start |
59 // probing. | 60 // probing. |
60 if (packet_size < PacedSender::kMinProbePacketSize) | 61 if (packet_size < PacedSender::kMinProbePacketSize) |
61 return; | 62 return; |
62 if (probing_state_ != kAllowedToProbe) | 63 if (probing_state_ != kAllowedToProbe) |
63 return; | 64 return; |
64 probe_bitrates_.clear(); | |
65 // Max number of packets used for probing. | 65 // Max number of packets used for probing. |
66 const int kMaxNumProbes = 2; | 66 const int kMaxNumProbes = 2; |
67 const int kPacketsPerProbe = 5; | 67 const int kPacketsPerProbe = 5; |
68 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6}; | 68 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6}; |
69 uint32_t bitrates_bps[kMaxNumProbes]; | |
70 std::stringstream bitrate_log; | 69 std::stringstream bitrate_log; |
71 bitrate_log << "Start probing for bandwidth, bitrates:"; | 70 bitrate_log << "Start probing for bandwidth, bitrates:"; |
72 for (int i = 0; i < kMaxNumProbes; ++i) { | 71 for (int i = 0; i < kMaxNumProbes; ++i) { |
73 bitrates_bps[i] = kProbeBitrateMultipliers[i] * bitrate_bps; | 72 ProbeCluster cluster; |
74 bitrate_log << " " << bitrates_bps[i]; | 73 // We need one extra to get 5 deltas for the first probe, therefore (i == 0) |
75 // We need one extra to get 5 deltas for the first probe. | 74 cluster.max_probe_packets = kPacketsPerProbe + (i == 0 ? 1 : 0); |
76 if (i == 0) | 75 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps; |
77 probe_bitrates_.push_back(bitrates_bps[i]); | 76 cluster.id = cluster_id_++; |
78 for (int j = 0; j < kPacketsPerProbe; ++j) | 77 |
79 probe_bitrates_.push_back(bitrates_bps[i]); | 78 bitrate_log << " " << cluster.probe_bitrate_bps; |
| 79 bitrate_log << ", num packets: " << cluster.max_probe_packets; |
| 80 |
| 81 clusters_.push(cluster); |
80 } | 82 } |
81 bitrate_log << ", num packets: " << probe_bitrates_.size(); | |
82 LOG(LS_INFO) << bitrate_log.str().c_str(); | 83 LOG(LS_INFO) << bitrate_log.str().c_str(); |
83 // Set last send time to current time so TimeUntilNextProbe doesn't short | 84 // Set last send time to current time so TimeUntilNextProbe doesn't short |
84 // circuit due to inactivity. | 85 // circuit due to inactivity. |
85 time_last_send_ms_ = now_ms; | 86 time_last_send_ms_ = now_ms; |
86 probing_state_ = kProbing; | 87 probing_state_ = kProbing; |
87 } | 88 } |
88 | 89 |
89 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { | 90 int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { |
90 if (probing_state_ != kDisabled && probe_bitrates_.empty()) { | 91 if (probing_state_ != kDisabled && clusters_.empty()) { |
91 probing_state_ = kWait; | 92 probing_state_ = kWait; |
92 } | 93 } |
93 if (probe_bitrates_.empty() || time_last_send_ms_ == -1) { | 94 |
| 95 if (clusters_.empty() || time_last_send_ms_ == -1) { |
94 // No probe started, probe finished, or too long since last probe packet. | 96 // No probe started, probe finished, or too long since last probe packet. |
95 return -1; | 97 return -1; |
96 } | 98 } |
97 int64_t elapsed_time_ms = now_ms - time_last_send_ms_; | 99 int64_t elapsed_time_ms = now_ms - time_last_send_ms_; |
98 // If no packets have been sent for n milliseconds, temporarily deactivate to | 100 // If no packets have been sent for n milliseconds, temporarily deactivate to |
99 // not keep spinning. | 101 // not keep spinning. |
100 static const int kInactiveSendDeltaMs = 5000; | 102 static const int kInactiveSendDeltaMs = 5000; |
101 if (elapsed_time_ms > kInactiveSendDeltaMs) { | 103 if (elapsed_time_ms > kInactiveSendDeltaMs) { |
102 time_last_send_ms_ = -1; | 104 time_last_send_ms_ = -1; |
103 probing_state_ = kAllowedToProbe; | 105 probing_state_ = kAllowedToProbe; |
104 return -1; | 106 return -1; |
105 } | 107 } |
106 // We will send the first probe packet immediately if no packet has been | 108 // We will send the first probe packet immediately if no packet has been |
107 // sent before. | 109 // sent before. |
108 int time_until_probe_ms = 0; | 110 int time_until_probe_ms = 0; |
109 if (packet_size_last_send_ != 0 && probing_state_ == kProbing) { | 111 if (packet_size_last_send_ != 0 && probing_state_ == kProbing) { |
110 int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_, | 112 int next_delta_ms = ComputeDeltaFromBitrate( |
111 probe_bitrates_.front()); | 113 packet_size_last_send_, clusters_.front().probe_bitrate_bps); |
112 time_until_probe_ms = next_delta_ms - elapsed_time_ms; | 114 time_until_probe_ms = next_delta_ms - elapsed_time_ms; |
113 // There is no point in trying to probe with less than 1 ms between packets | 115 // There is no point in trying to probe with less than 1 ms between packets |
114 // as it essentially means trying to probe at infinite bandwidth. | 116 // as it essentially means trying to probe at infinite bandwidth. |
115 const int kMinProbeDeltaMs = 1; | 117 const int kMinProbeDeltaMs = 1; |
116 // If we have waited more than 3 ms for a new packet to probe with we will | 118 // If we have waited more than 3 ms for a new packet to probe with we will |
117 // consider this probing session over. | 119 // consider this probing session over. |
118 const int kMaxProbeDelayMs = 3; | 120 const int kMaxProbeDelayMs = 3; |
119 if (next_delta_ms < kMinProbeDeltaMs || | 121 if (next_delta_ms < kMinProbeDeltaMs || |
120 time_until_probe_ms < -kMaxProbeDelayMs) { | 122 time_until_probe_ms < -kMaxProbeDelayMs) { |
121 // We currently disable probing after the first probe, as we only want | 123 // We currently disable probing after the first probe, as we only want |
122 // to probe at the beginning of a connection. We should set this to | 124 // to probe at the beginning of a connection. We should set this to |
123 // kWait if we later want to probe periodically. | 125 // kWait if we later want to probe periodically. |
124 probing_state_ = kWait; | 126 probing_state_ = kWait; |
125 LOG(LS_INFO) << "Next delta too small, stop probing."; | 127 LOG(LS_INFO) << "Next delta too small, stop probing."; |
126 time_until_probe_ms = 0; | 128 time_until_probe_ms = 0; |
127 } | 129 } |
128 } | 130 } |
129 return std::max(time_until_probe_ms, 0); | 131 return std::max(time_until_probe_ms, 0); |
130 } | 132 } |
131 | 133 |
| 134 int BitrateProber::CurrentClusterId() const { |
| 135 RTC_DCHECK(!clusters_.empty()); |
| 136 RTC_DCHECK_EQ(kProbing, probing_state_); |
| 137 return clusters_.front().id; |
| 138 } |
| 139 |
132 size_t BitrateProber::RecommendedPacketSize() const { | 140 size_t BitrateProber::RecommendedPacketSize() const { |
133 return packet_size_last_send_; | 141 return packet_size_last_send_; |
134 } | 142 } |
135 | 143 |
136 void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) { | 144 void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) { |
137 assert(packet_size > 0); | 145 assert(packet_size > 0); |
138 if (packet_size < PacedSender::kMinProbePacketSize) | 146 if (packet_size < PacedSender::kMinProbePacketSize) |
139 return; | 147 return; |
140 packet_size_last_send_ = packet_size; | 148 packet_size_last_send_ = packet_size; |
141 time_last_send_ms_ = now_ms; | 149 time_last_send_ms_ = now_ms; |
142 if (probing_state_ != kProbing) | 150 if (probing_state_ != kProbing) |
143 return; | 151 return; |
144 if (!probe_bitrates_.empty()) | 152 if (!clusters_.empty()) { |
145 probe_bitrates_.pop_front(); | 153 ProbeCluster* cluster = &clusters_.front(); |
| 154 ++cluster->sent_probe_packets; |
| 155 if (cluster->sent_probe_packets == cluster->max_probe_packets) |
| 156 clusters_.pop(); |
| 157 } |
146 } | 158 } |
147 } // namespace webrtc | 159 } // namespace webrtc |
OLD | NEW |