blob: bedb892267e05ca3e804db53e5133ea9b9e2be77 [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
18#include "webrtc/system_wrappers/interface/logging.h"
19
20namespace webrtc {
21
22namespace {
23int ComputeDeltaFromBitrate(size_t packet_size, int bitrate_bps) {
24 assert(bitrate_bps > 0);
25 // Compute the time delta needed to send packet_size bytes at bitrate_bps
26 // bps. Result is in milliseconds.
27 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll /
28 bitrate_bps);
29}
30} // namespace
31
stefanfe0c9052015-07-27 03:13:32 -070032const size_t BitrateProber::kMinProbePacketSize = 200;
33
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000034BitrateProber::BitrateProber()
35 : probing_state_(kDisabled),
36 packet_size_last_send_(0),
37 time_last_send_ms_(-1) {
38}
39
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
56void BitrateProber::MaybeInitializeProbe(int bitrate_bps) {
57 if (probing_state_ != kAllowedToProbe)
58 return;
59 probe_bitrates_.clear();
60 // Max number of packets used for probing.
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000061 const int kMaxNumProbes = 2;
62 const int kPacketsPerProbe = 5;
63 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000064 int bitrates_bps[kMaxNumProbes];
65 std::stringstream bitrate_log;
66 bitrate_log << "Start probing for bandwidth, bitrates:";
67 for (int i = 0; i < kMaxNumProbes; ++i) {
68 bitrates_bps[i] = kProbeBitrateMultipliers[i] * bitrate_bps;
69 bitrate_log << " " << bitrates_bps[i];
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000070 // We need one extra to get 5 deltas for the first probe.
71 if (i == 0)
72 probe_bitrates_.push_back(bitrates_bps[i]);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000073 for (int j = 0; j < kPacketsPerProbe; ++j)
74 probe_bitrates_.push_back(bitrates_bps[i]);
75 }
76 bitrate_log << ", num packets: " << probe_bitrates_.size();
77 LOG(LS_INFO) << bitrate_log.str().c_str();
78 probing_state_ = kProbing;
79}
80
81int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
82 if (probing_state_ != kDisabled && probe_bitrates_.empty()) {
83 probing_state_ = kWait;
84 }
85 if (probe_bitrates_.empty()) {
86 // No probe started, or waiting for next probe.
stefan@webrtc.orge9f0f592015-02-16 15:47:51 +000087 return -1;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000088 }
89 int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
90 // We will send the first probe packet immediately if no packet has been
91 // sent before.
92 int time_until_probe_ms = 0;
stefanfe0c9052015-07-27 03:13:32 -070093 if (packet_size_last_send_ > kMinProbePacketSize &&
94 probing_state_ == kProbing) {
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000095 int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_,
96 probe_bitrates_.front());
97 time_until_probe_ms = next_delta_ms - elapsed_time_ms;
98 // There is no point in trying to probe with less than 1 ms between packets
99 // as it essentially means trying to probe at infinite bandwidth.
100 const int kMinProbeDeltaMs = 1;
101 // If we have waited more than 3 ms for a new packet to probe with we will
102 // consider this probing session over.
103 const int kMaxProbeDelayMs = 3;
104 if (next_delta_ms < kMinProbeDeltaMs ||
105 time_until_probe_ms < -kMaxProbeDelayMs) {
106 // We currently disable probing after the first probe, as we only want
107 // to probe at the beginning of a connection. We should set this to
108 // kWait if we later want to probe periodically.
109 probing_state_ = kWait;
110 LOG(LS_INFO) << "Next delta too small, stop probing.";
111 time_until_probe_ms = 0;
112 }
113 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200114 return std::max(time_until_probe_ms, 0);
115}
116
117size_t BitrateProber::RecommendedPacketSize() const {
118 return packet_size_last_send_;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000119}
120
121void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
122 assert(packet_size > 0);
123 packet_size_last_send_ = packet_size;
124 time_last_send_ms_ = now_ms;
125 if (probing_state_ != kProbing)
126 return;
127 if (!probe_bitrates_.empty())
128 probe_bitrates_.pop_front();
129}
130} // namespace webrtc