1 /* 2 * libjingle 3 * Copyright 2011, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/bandwidthsmoother.h" 29 30 #include <limits.h> 31 32 namespace talk_base { 33 34 BandwidthSmoother::BandwidthSmoother(int initial_bandwidth_guess, 35 uint32 time_between_increase, 36 double percent_increase, 37 size_t samples_count_to_average, 38 double min_sample_count_percent) 39 : time_between_increase_(time_between_increase), 40 percent_increase_(talk_base::_max(1.0, percent_increase)), 41 time_at_last_change_(0), 42 bandwidth_estimation_(initial_bandwidth_guess), 43 accumulator_(samples_count_to_average), 44 min_sample_count_percent_( 45 talk_base::_min(1.0, 46 talk_base::_max(0.0, min_sample_count_percent))) { 47 } 48 49 // Samples a new bandwidth measurement 50 // returns true if the bandwidth estimation changed 51 bool BandwidthSmoother::Sample(uint32 sample_time, int bandwidth) { 52 if (bandwidth < 0) { 53 return false; 54 } 55 56 accumulator_.AddSample(bandwidth); 57 58 if (accumulator_.count() < static_cast<size_t>( 59 accumulator_.max_count() * min_sample_count_percent_)) { 60 // We have not collected enough samples yet. 61 return false; 62 } 63 64 // Replace bandwidth with the mean of sampled bandwidths. 65 const int mean_bandwidth = accumulator_.ComputeMean(); 66 67 if (mean_bandwidth < bandwidth_estimation_) { 68 time_at_last_change_ = sample_time; 69 bandwidth_estimation_ = mean_bandwidth; 70 return true; 71 } 72 73 const int old_bandwidth_estimation = bandwidth_estimation_; 74 const double increase_threshold_d = percent_increase_ * bandwidth_estimation_; 75 if (increase_threshold_d > INT_MAX) { 76 // If bandwidth goes any higher we would overflow. 77 return false; 78 } 79 80 const int increase_threshold = static_cast<int>(increase_threshold_d); 81 if (mean_bandwidth < increase_threshold) { 82 time_at_last_change_ = sample_time; 83 // The value of bandwidth_estimation remains the same if we don't exceed 84 // percent_increase_ * bandwidth_estimation_ for at least 85 // time_between_increase_ time. 86 } else if (sample_time >= time_at_last_change_ + time_between_increase_) { 87 time_at_last_change_ = sample_time; 88 if (increase_threshold == 0) { 89 // Bandwidth_estimation_ must be zero. Assume a jump from zero to a 90 // positive bandwidth means we have regained connectivity. 91 bandwidth_estimation_ = mean_bandwidth; 92 } else { 93 bandwidth_estimation_ = increase_threshold; 94 } 95 } 96 // Else don't make a change. 97 98 return old_bandwidth_estimation != bandwidth_estimation_; 99 } 100 101 } // namespace talk_base 102