blob: c5aa983266c4c923b7189675a68fadfbff5e508d [file] [log] [blame]
stefan@webrtc.org82462aa2014-10-23 11:57:05 +00001/*
2 * Copyright (c) 2014 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/pacing/bitrate_prober.h"
12
13#include <assert.h>
Stefan Holmer01b48882015-05-05 10:21:24 +020014#include <algorithm>
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000015#include <limits>
16#include <sstream>
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070017#include <utility>
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000018
philipeldd324862016-05-06 17:06:14 +020019#include "webrtc/base/checks.h"
Peter Boström7c704b82015-12-04 16:13:05 +010020#include "webrtc/base/logging.h"
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010021#include "webrtc/modules/pacing/paced_sender.h"
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000022
23namespace webrtc {
24
25namespace {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070026
27// Inactivity threshold above which probing is restarted.
28constexpr int kInactivityThresholdMs = 5000;
29
Per28a44562016-05-04 17:12:51 +020030int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) {
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000031 assert(bitrate_bps > 0);
32 // Compute the time delta needed to send packet_size bytes at bitrate_bps
33 // bps. Result is in milliseconds.
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070034 return static_cast<int>((1000ll * packet_size * 8) / bitrate_bps);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000035}
36} // namespace
37
38BitrateProber::BitrateProber()
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070039 : probing_state_(ProbingState::kDisabled),
40 packet_size_last_sent_(0),
41 time_last_probe_sent_ms_(-1),
42 next_cluster_id_(0) {
43 SetEnabled(true);
44}
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000045
46void BitrateProber::SetEnabled(bool enable) {
47 if (enable) {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070048 if (probing_state_ == ProbingState::kDisabled) {
49 probing_state_ = ProbingState::kInactive;
50 LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive";
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000051 }
52 } else {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070053 probing_state_ = ProbingState::kDisabled;
54 LOG(LS_INFO) << "Bandwidth probing disabled";
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000055 }
56}
57
58bool BitrateProber::IsProbing() const {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070059 return probing_state_ == ProbingState::kActive;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000060}
61
Per28a44562016-05-04 17:12:51 +020062void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps,
Peter Boström0453ef82016-02-16 16:23:08 +010063 size_t packet_size,
64 int64_t now_ms) {
65 // Don't initialize probing unless we have something large enough to start
66 // probing.
67 if (packet_size < PacedSender::kMinProbePacketSize)
68 return;
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070069 if (probing_state_ != ProbingState::kInactive)
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000070 return;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000071 // Max number of packets used for probing.
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000072 const int kMaxNumProbes = 2;
73 const int kPacketsPerProbe = 5;
74 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000075 std::stringstream bitrate_log;
philipel29dca2c2016-05-13 11:13:05 +020076 bitrate_log << "Start probing for bandwidth, (bitrate:packets): ";
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000077 for (int i = 0; i < kMaxNumProbes; ++i) {
philipeldd324862016-05-06 17:06:14 +020078 ProbeCluster cluster;
79 // 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);
81 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps;
philipel29dca2c2016-05-13 11:13:05 +020082 cluster.id = next_cluster_id_++;
philipeldd324862016-05-06 17:06:14 +020083
philipel29dca2c2016-05-13 11:13:05 +020084 bitrate_log << "(" << cluster.probe_bitrate_bps << ":"
85 << cluster.max_probe_packets << ") ";
philipeldd324862016-05-06 17:06:14 +020086
87 clusters_.push(cluster);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000088 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000089 LOG(LS_INFO) << bitrate_log.str().c_str();
Irfan Sheriff6e11efa2016-08-02 12:57:37 -070090 probing_state_ = ProbingState::kActive;
91}
92
93void BitrateProber::ResetState() {
94 time_last_probe_sent_ms_ = -1;
95 packet_size_last_sent_ = 0;
96 clusters_ = std::queue<ProbeCluster>();
97 // If its enabled, reset to inactive.
98 if (probing_state_ != ProbingState::kDisabled)
99 probing_state_ = ProbingState::kInactive;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000100}
101
102int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700103 // Probing is not active or probing is already complete.
104 if (probing_state_ != ProbingState::kActive || clusters_.empty())
stefan@webrtc.orge9f0f592015-02-16 15:47:51 +0000105 return -1;
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700106 // time_last_probe_sent_ms_ of -1 indicates no probes have yet been sent.
107 int64_t elapsed_time_ms;
108 if (time_last_probe_sent_ms_ == -1) {
109 elapsed_time_ms = 0;
110 } else {
111 elapsed_time_ms = now_ms - time_last_probe_sent_ms_;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000112 }
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700113 // If no probes have been sent for a while, abort current probing and
114 // reset.
115 if (elapsed_time_ms > kInactivityThresholdMs) {
116 ResetState();
Peter Boström0453ef82016-02-16 16:23:08 +0100117 return -1;
118 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000119 // We will send the first probe packet immediately if no packet has been
120 // sent before.
121 int time_until_probe_ms = 0;
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700122 if (packet_size_last_sent_ != 0 && probing_state_ == ProbingState::kActive) {
philipeldd324862016-05-06 17:06:14 +0200123 int next_delta_ms = ComputeDeltaFromBitrate(
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700124 packet_size_last_sent_, clusters_.front().probe_bitrate_bps);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000125 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
127 // as it essentially means trying to probe at infinite bandwidth.
128 const int kMinProbeDeltaMs = 1;
129 // If we have waited more than 3 ms for a new packet to probe with we will
130 // consider this probing session over.
131 const int kMaxProbeDelayMs = 3;
132 if (next_delta_ms < kMinProbeDeltaMs ||
133 time_until_probe_ms < -kMaxProbeDelayMs) {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700134 probing_state_ = ProbingState::kSuspended;
135 LOG(LS_INFO) << "Delta too small or missed probing accurately, suspend";
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000136 time_until_probe_ms = 0;
137 }
138 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200139 return std::max(time_until_probe_ms, 0);
140}
141
philipeldd324862016-05-06 17:06:14 +0200142int BitrateProber::CurrentClusterId() const {
143 RTC_DCHECK(!clusters_.empty());
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700144 RTC_DCHECK(ProbingState::kActive == probing_state_);
philipeldd324862016-05-06 17:06:14 +0200145 return clusters_.front().id;
146}
147
Stefan Holmer01b48882015-05-05 10:21:24 +0200148size_t BitrateProber::RecommendedPacketSize() const {
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700149 return packet_size_last_sent_;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000150}
151
152void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
153 assert(packet_size > 0);
Peter Boström0453ef82016-02-16 16:23:08 +0100154 if (packet_size < PacedSender::kMinProbePacketSize)
155 return;
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700156 packet_size_last_sent_ = packet_size;
157 if (probing_state_ != ProbingState::kActive)
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000158 return;
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700159 time_last_probe_sent_ms_ = now_ms;
philipeldd324862016-05-06 17:06:14 +0200160 if (!clusters_.empty()) {
161 ProbeCluster* cluster = &clusters_.front();
162 ++cluster->sent_probe_packets;
163 if (cluster->sent_probe_packets == cluster->max_probe_packets)
164 clusters_.pop();
philipel1a93cde2016-06-03 01:41:45 -0700165 if (clusters_.empty())
Irfan Sheriff6e11efa2016-08-02 12:57:37 -0700166 probing_state_ = ProbingState::kSuspended;
philipeldd324862016-05-06 17:06:14 +0200167 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000168}
169} // namespace webrtc