1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/*
2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *
4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */
10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/bandwidthsmoother.h"
12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include <limits.h>
14ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org#include <algorithm>
15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgnamespace rtc {
17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgBandwidthSmoother::BandwidthSmoother(int initial_bandwidth_guess,
190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint32_t time_between_increase,
20f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                     double percent_increase,
21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                     size_t samples_count_to_average,
22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                     double min_sample_count_percent)
23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    : time_between_increase_(time_between_increase),
24ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org      percent_increase_(std::max(1.0, percent_increase)),
25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      time_at_last_change_(0),
26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      bandwidth_estimation_(initial_bandwidth_guess),
27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      accumulator_(samples_count_to_average),
28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      min_sample_count_percent_(
29ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org          std::min(1.0, std::max(0.0, min_sample_count_percent))) {
30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
3267186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.orgBandwidthSmoother::~BandwidthSmoother() = default;
3367186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org
34f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Samples a new bandwidth measurement
35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// returns true if the bandwidth estimation changed
360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool BandwidthSmoother::Sample(uint32_t sample_time, int bandwidth) {
37f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (bandwidth < 0) {
38f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  accumulator_.AddSample(bandwidth);
42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (accumulator_.count() < static_cast<size_t>(
44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org          accumulator_.max_count() * min_sample_count_percent_)) {
45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // We have not collected enough samples yet.
46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Replace bandwidth with the mean of sampled bandwidths.
50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const int mean_bandwidth = static_cast<int>(accumulator_.ComputeMean());
51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (mean_bandwidth < bandwidth_estimation_) {
53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    time_at_last_change_ = sample_time;
54f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    bandwidth_estimation_ = mean_bandwidth;
55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return true;
56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const int old_bandwidth_estimation = bandwidth_estimation_;
59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const double increase_threshold_d = percent_increase_ * bandwidth_estimation_;
60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (increase_threshold_d > INT_MAX) {
61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // If bandwidth goes any higher we would overflow.
62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const int increase_threshold = static_cast<int>(increase_threshold_d);
66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (mean_bandwidth < increase_threshold) {
67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    time_at_last_change_ = sample_time;
68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // The value of bandwidth_estimation remains the same if we don't exceed
69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // percent_increase_ * bandwidth_estimation_ for at least
70f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // time_between_increase_ time.
71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else if (sample_time >= time_at_last_change_ + time_between_increase_) {
72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    time_at_last_change_ = sample_time;
73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (increase_threshold == 0) {
74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // Bandwidth_estimation_ must be zero. Assume a jump from zero to a
75f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // positive bandwidth means we have regained connectivity.
76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      bandwidth_estimation_ = mean_bandwidth;
77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    } else {
78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      bandwidth_estimation_ = increase_threshold;
79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Else don't make a change.
82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return old_bandwidth_estimation != bandwidth_estimation_;
84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}  // namespace rtc
87