blob: 1ed6298ff11f6804982d5a3701a02954c6c1054e [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
32BitrateProber::BitrateProber()
33 : probing_state_(kDisabled),
34 packet_size_last_send_(0),
35 time_last_send_ms_(-1) {
36}
37
38void BitrateProber::SetEnabled(bool enable) {
39 if (enable) {
40 if (probing_state_ == kDisabled) {
41 probing_state_ = kAllowedToProbe;
42 LOG(LS_INFO) << "Initial bandwidth probing enabled";
43 }
44 } else {
45 probing_state_ = kDisabled;
46 LOG(LS_INFO) << "Initial bandwidth probing disabled";
47 }
48}
49
50bool BitrateProber::IsProbing() const {
51 return probing_state_ == kProbing;
52}
53
54void BitrateProber::MaybeInitializeProbe(int bitrate_bps) {
55 if (probing_state_ != kAllowedToProbe)
56 return;
57 probe_bitrates_.clear();
58 // Max number of packets used for probing.
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000059 const int kMaxNumProbes = 2;
60 const int kPacketsPerProbe = 5;
61 const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000062 int bitrates_bps[kMaxNumProbes];
63 std::stringstream bitrate_log;
64 bitrate_log << "Start probing for bandwidth, bitrates:";
65 for (int i = 0; i < kMaxNumProbes; ++i) {
66 bitrates_bps[i] = kProbeBitrateMultipliers[i] * bitrate_bps;
67 bitrate_log << " " << bitrates_bps[i];
stefan@webrtc.orgd839e0a2014-11-04 19:33:55 +000068 // We need one extra to get 5 deltas for the first probe.
69 if (i == 0)
70 probe_bitrates_.push_back(bitrates_bps[i]);
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000071 for (int j = 0; j < kPacketsPerProbe; ++j)
72 probe_bitrates_.push_back(bitrates_bps[i]);
73 }
74 bitrate_log << ", num packets: " << probe_bitrates_.size();
75 LOG(LS_INFO) << bitrate_log.str().c_str();
76 probing_state_ = kProbing;
77}
78
79int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
80 if (probing_state_ != kDisabled && probe_bitrates_.empty()) {
81 probing_state_ = kWait;
82 }
83 if (probe_bitrates_.empty()) {
84 // No probe started, or waiting for next probe.
stefan@webrtc.orge9f0f592015-02-16 15:47:51 +000085 return -1;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +000086 }
87 int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
88 // We will send the first probe packet immediately if no packet has been
89 // sent before.
90 int time_until_probe_ms = 0;
91 if (packet_size_last_send_ > 0 && probing_state_ == kProbing) {
92 int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_,
93 probe_bitrates_.front());
94 time_until_probe_ms = next_delta_ms - elapsed_time_ms;
95 // There is no point in trying to probe with less than 1 ms between packets
96 // as it essentially means trying to probe at infinite bandwidth.
97 const int kMinProbeDeltaMs = 1;
98 // If we have waited more than 3 ms for a new packet to probe with we will
99 // consider this probing session over.
100 const int kMaxProbeDelayMs = 3;
101 if (next_delta_ms < kMinProbeDeltaMs ||
102 time_until_probe_ms < -kMaxProbeDelayMs) {
103 // We currently disable probing after the first probe, as we only want
104 // to probe at the beginning of a connection. We should set this to
105 // kWait if we later want to probe periodically.
106 probing_state_ = kWait;
107 LOG(LS_INFO) << "Next delta too small, stop probing.";
108 time_until_probe_ms = 0;
109 }
110 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200111 return std::max(time_until_probe_ms, 0);
112}
113
114size_t BitrateProber::RecommendedPacketSize() const {
115 return packet_size_last_send_;
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000116}
117
118void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
119 assert(packet_size > 0);
120 packet_size_last_send_ = packet_size;
121 time_last_send_ms_ = now_ms;
122 if (probing_state_ != kProbing)
123 return;
124 if (!probe_bitrates_.empty())
125 probe_bitrates_.pop_front();
126}
127} // namespace webrtc