blob: 8e8e36ea34be202017e81ff584bb9ec7b26e9079 [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>
17
philipeldd324862016-05-06 17:06:14 +020018#include "webrtc/base/checks.h"
Peter Boström7c704b82015-12-04 16:13:05 +010019#include "webrtc/base/logging.h"
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010020#include "webrtc/modules/pacing/paced_sender.h"
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000021
22namespace webrtc {
23
24namespace {
Per28a44562016-05-04 17:12:51 +020025int ComputeDeltaFromBitrate(size_t packet_size, uint32_t bitrate_bps) {
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000026 assert(bitrate_bps > 0);
27 // Compute the time delta needed to send packet_size bytes at bitrate_bps
28 // bps. Result is in milliseconds.
29 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll /
30 bitrate_bps);
31}
32} // namespace
33
34BitrateProber::BitrateProber()
35 : probing_state_(kDisabled),
36 packet_size_last_send_(0),
philipeldd324862016-05-06 17:06:14 +020037 time_last_send_ms_(-1),
philipel29dca2c2016-05-13 11:13:05 +020038 next_cluster_id_(0) {}
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000039
40void BitrateProber::SetEnabled(bool enable) {
41 if (enable) {
42 if (probing_state_ == kDisabled) {
43 probing_state_ = kAllowedToProbe;
44 LOG(LS_INFO) << "Initial bandwidth probing enabled";
45 }
46 } else {
47 probing_state_ = kDisabled;
48 LOG(LS_INFO) << "Initial bandwidth probing disabled";
49 }
50}
51
52bool BitrateProber::IsProbing() const {
53 return probing_state_ == kProbing;
54}
55
Per28a44562016-05-04 17:12:51 +020056void BitrateProber::OnIncomingPacket(uint32_t bitrate_bps,
Peter Boström0453ef82016-02-16 16:23:08 +010057 size_t packet_size,
58 int64_t now_ms) {
59 // Don't initialize probing unless we have something large enough to start
60 // probing.
61 if (packet_size < PacedSender::kMinProbePacketSize)
62 return;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000063 if (probing_state_ != kAllowedToProbe)
64 return;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000065 // Max number of packets used for probing.
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000066 const int kMaxNumProbes = 2;
67 const int kPacketsPerProbe = 5;
68 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000069 std::stringstream bitrate_log;
philipel29dca2c2016-05-13 11:13:05 +020070 bitrate_log << "Start probing for bandwidth, (bitrate:packets): ";
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000071 for (int i = 0; i < kMaxNumProbes; ++i) {
philipeldd324862016-05-06 17:06:14 +020072 ProbeCluster cluster;
73 // 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);
75 cluster.probe_bitrate_bps = kProbeBitrateMultipliers[i] * bitrate_bps;
philipel29dca2c2016-05-13 11:13:05 +020076 cluster.id = next_cluster_id_++;
philipeldd324862016-05-06 17:06:14 +020077
philipel29dca2c2016-05-13 11:13:05 +020078 bitrate_log << "(" << cluster.probe_bitrate_bps << ":"
79 << cluster.max_probe_packets << ") ";
philipeldd324862016-05-06 17:06:14 +020080
81 clusters_.push(cluster);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000082 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000083 LOG(LS_INFO) << bitrate_log.str().c_str();
Peter Boström0453ef82016-02-16 16:23:08 +010084 // Set last send time to current time so TimeUntilNextProbe doesn't short
85 // circuit due to inactivity.
86 time_last_send_ms_ = now_ms;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000087 probing_state_ = kProbing;
88}
89
90int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
philipeldd324862016-05-06 17:06:14 +020091 if (probing_state_ != kDisabled && clusters_.empty()) {
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000092 probing_state_ = kWait;
93 }
philipeldd324862016-05-06 17:06:14 +020094
95 if (clusters_.empty() || time_last_send_ms_ == -1) {
Peter Boström0453ef82016-02-16 16:23:08 +010096 // No probe started, probe finished, or too long since last probe packet.
stefan@webrtc.orge9f0f592015-02-16 15:47:51 +000097 return -1;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000098 }
99 int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
Peter Boström0453ef82016-02-16 16:23:08 +0100100 // 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;
107 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000108 // We will send the first probe packet immediately if no packet has been
109 // sent before.
110 int time_until_probe_ms = 0;
Peter Boström0453ef82016-02-16 16:23:08 +0100111 if (packet_size_last_send_ != 0 && probing_state_ == kProbing) {
philipeldd324862016-05-06 17:06:14 +0200112 int next_delta_ms = ComputeDeltaFromBitrate(
113 packet_size_last_send_, clusters_.front().probe_bitrate_bps);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000114 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
116 // as it essentially means trying to probe at infinite bandwidth.
117 const int kMinProbeDeltaMs = 1;
118 // If we have waited more than 3 ms for a new packet to probe with we will
119 // consider this probing session over.
120 const int kMaxProbeDelayMs = 3;
121 if (next_delta_ms < kMinProbeDeltaMs ||
122 time_until_probe_ms < -kMaxProbeDelayMs) {
123 // We currently disable probing after the first probe, as we only want
124 // to probe at the beginning of a connection. We should set this to
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;
129 }
130 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200131 return std::max(time_until_probe_ms, 0);
132}
133
philipeldd324862016-05-06 17:06:14 +0200134int BitrateProber::CurrentClusterId() const {
135 RTC_DCHECK(!clusters_.empty());
136 RTC_DCHECK_EQ(kProbing, probing_state_);
137 return clusters_.front().id;
138}
139
Stefan Holmer01b48882015-05-05 10:21:24 +0200140size_t BitrateProber::RecommendedPacketSize() const {
141 return packet_size_last_send_;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000142}
143
144void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
145 assert(packet_size > 0);
Peter Boström0453ef82016-02-16 16:23:08 +0100146 if (packet_size < PacedSender::kMinProbePacketSize)
147 return;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000148 packet_size_last_send_ = packet_size;
149 time_last_send_ms_ = now_ms;
150 if (probing_state_ != kProbing)
151 return;
philipeldd324862016-05-06 17:06:14 +0200152 if (!clusters_.empty()) {
153 ProbeCluster* cluster = &clusters_.front();
154 ++cluster->sent_probe_packets;
155 if (cluster->sent_probe_packets == cluster->max_probe_packets)
156 clusters_.pop();
157 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000158}
159} // namespace webrtc