blob: fc8787a3ff4025d3b155871a98465750b0f50224 [file] [log] [blame]
palmkvist349092b2016-12-13 02:45:57 -08001/*
2 * Copyright (c) 2016 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/quality_threshold.h"
palmkvist349092b2016-12-13 02:45:57 -080012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
14#include "rtc_base/logging.h"
palmkvist349092b2016-12-13 02:45:57 -080015
16namespace webrtc {
17
18QualityThreshold::QualityThreshold(int low_threshold,
19 int high_threshold,
20 float fraction,
21 int max_measurements)
22 : buffer_(new int[max_measurements]),
23 max_measurements_(max_measurements),
24 fraction_(fraction),
25 low_threshold_(low_threshold),
26 high_threshold_(high_threshold),
27 until_full_(max_measurements),
28 next_index_(0),
29 sum_(0),
30 count_low_(0),
palmkvista40672a2017-01-13 05:58:34 -080031 count_high_(0),
32 num_high_states_(0),
33 num_certain_states_(0) {
palmkvist349092b2016-12-13 02:45:57 -080034 RTC_CHECK_GT(fraction, 0.5f);
35 RTC_CHECK_GT(max_measurements, 1);
36 RTC_CHECK_LT(low_threshold, high_threshold);
37}
38
39void QualityThreshold::AddMeasurement(int measurement) {
40 int prev_val = until_full_ > 0 ? 0 : buffer_[next_index_];
41 buffer_[next_index_] = measurement;
42 next_index_ = (next_index_ + 1) % max_measurements_;
43
44 sum_ += measurement - prev_val;
45
46 if (until_full_ == 0) {
47 if (prev_val <= low_threshold_) {
48 --count_low_;
49 } else if (prev_val >= high_threshold_) {
50 --count_high_;
51 }
52 }
53
54 if (measurement <= low_threshold_) {
55 ++count_low_;
56 } else if (measurement >= high_threshold_) {
57 ++count_high_;
58 }
59
60 float sufficient_majority = fraction_ * max_measurements_;
61 if (count_high_ >= sufficient_majority) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +010062 is_high_ = true;
palmkvist349092b2016-12-13 02:45:57 -080063 } else if (count_low_ >= sufficient_majority) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +010064 is_high_ = false;
palmkvist349092b2016-12-13 02:45:57 -080065 }
66
67 if (until_full_ > 0)
68 --until_full_;
palmkvista40672a2017-01-13 05:58:34 -080069
70 if (is_high_) {
71 if (*is_high_)
72 ++num_high_states_;
73 ++num_certain_states_;
74 }
palmkvist349092b2016-12-13 02:45:57 -080075}
76
77rtc::Optional<bool> QualityThreshold::IsHigh() const {
78 return is_high_;
79}
80
81rtc::Optional<double> QualityThreshold::CalculateVariance() const {
82 if (until_full_ > 0) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +010083 return rtc::nullopt;
palmkvist349092b2016-12-13 02:45:57 -080084 }
85
86 double variance = 0;
87 double mean = static_cast<double>(sum_) / max_measurements_;
88 for (int i = 0; i < max_measurements_; ++i) {
89 variance += (buffer_[i] - mean) * (buffer_[i] - mean);
90 }
Oskar Sundbom8e07c132018-01-08 16:45:42 +010091 return variance / (max_measurements_ - 1);
palmkvist349092b2016-12-13 02:45:57 -080092}
93
palmkvista40672a2017-01-13 05:58:34 -080094rtc::Optional<double> QualityThreshold::FractionHigh(
95 int min_required_samples) const {
96 RTC_DCHECK_GT(min_required_samples, 0);
97 if (num_certain_states_ < min_required_samples)
Oskar Sundbom8e07c132018-01-08 16:45:42 +010098 return rtc::nullopt;
palmkvista40672a2017-01-13 05:58:34 -080099
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100100 return static_cast<double>(num_high_states_) / num_certain_states_;
palmkvista40672a2017-01-13 05:58:34 -0800101}
102
palmkvist349092b2016-12-13 02:45:57 -0800103} // namespace webrtc