blob: 04e71c5c28b1aee81e19c239d395f6e025a57d09 [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>
14#include <limits>
15#include <sstream>
16
17#include "webrtc/system_wrappers/interface/logging.h"
18
19namespace webrtc {
20
21namespace {
22int ComputeDeltaFromBitrate(size_t packet_size, int bitrate_bps) {
23 assert(bitrate_bps > 0);
24 // Compute the time delta needed to send packet_size bytes at bitrate_bps
25 // bps. Result is in milliseconds.
26 return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll /
27 bitrate_bps);
28}
29} // namespace
30
31BitrateProber::BitrateProber()
32 : probing_state_(kDisabled),
33 packet_size_last_send_(0),
34 time_last_send_ms_(-1) {
35}
36
37void BitrateProber::SetEnabled(bool enable) {
38 if (enable) {
39 if (probing_state_ == kDisabled) {
40 probing_state_ = kAllowedToProbe;
41 LOG(LS_INFO) << "Initial bandwidth probing enabled";
42 }
43 } else {
44 probing_state_ = kDisabled;
45 LOG(LS_INFO) << "Initial bandwidth probing disabled";
46 }
47}
48
49bool BitrateProber::IsProbing() const {
50 return probing_state_ == kProbing;
51}
52
53void BitrateProber::MaybeInitializeProbe(int bitrate_bps) {
54 if (probing_state_ != kAllowedToProbe)
55 return;
56 probe_bitrates_.clear();
57 // Max number of packets used for probing.
58 const int kMaxProbeLength = 15;
59 const int kMaxNumProbes = 3;
60 const int kPacketsPerProbe = kMaxProbeLength / kMaxNumProbes;
61 const float kProbeBitrateMultipliers[kMaxNumProbes] = {2.5, 4, 6};
62 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];
68 for (int j = 0; j < kPacketsPerProbe; ++j)
69 probe_bitrates_.push_back(bitrates_bps[i]);
70 }
71 bitrate_log << ", num packets: " << probe_bitrates_.size();
72 LOG(LS_INFO) << bitrate_log.str().c_str();
73 probing_state_ = kProbing;
74}
75
76int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
77 if (probing_state_ != kDisabled && probe_bitrates_.empty()) {
78 probing_state_ = kWait;
79 }
80 if (probe_bitrates_.empty()) {
81 // No probe started, or waiting for next probe.
82 return std::numeric_limits<int>::max();
83 }
84 int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
85 // We will send the first probe packet immediately if no packet has been
86 // sent before.
87 int time_until_probe_ms = 0;
88 if (packet_size_last_send_ > 0 && probing_state_ == kProbing) {
89 int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_,
90 probe_bitrates_.front());
91 time_until_probe_ms = next_delta_ms - elapsed_time_ms;
92 // There is no point in trying to probe with less than 1 ms between packets
93 // as it essentially means trying to probe at infinite bandwidth.
94 const int kMinProbeDeltaMs = 1;
95 // If we have waited more than 3 ms for a new packet to probe with we will
96 // consider this probing session over.
97 const int kMaxProbeDelayMs = 3;
98 if (next_delta_ms < kMinProbeDeltaMs ||
99 time_until_probe_ms < -kMaxProbeDelayMs) {
100 // We currently disable probing after the first probe, as we only want
101 // to probe at the beginning of a connection. We should set this to
102 // kWait if we later want to probe periodically.
103 probing_state_ = kWait;
104 LOG(LS_INFO) << "Next delta too small, stop probing.";
105 time_until_probe_ms = 0;
106 }
107 }
108 return time_until_probe_ms;
109}
110
111void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
112 assert(packet_size > 0);
113 packet_size_last_send_ = packet_size;
114 time_last_send_ms_ = now_ms;
115 if (probing_state_ != kProbing)
116 return;
117 if (!probe_bitrates_.empty())
118 probe_bitrates_.pop_front();
119}
120} // namespace webrtc