Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: media/capture/content/feedback_signal_accumulator.h

Issue 2149793003: Move media/capture/content/feedback_signal_accumulator{.h,_unittest.cc} to media/base (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_
6 #define MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_
7
8 #include "base/time/time.h"
9 #include "media/capture/capture_export.h"
10
11 namespace media {
12
13 // Utility class for maintaining an exponentially-decaying average of feedback
14 // signal values whose updates occur at undetermined, possibly irregular time
15 // intervals.
16 //
17 // Feedback signals can be made by multiple sources. Meaning, there can be
18 // several values provided for the same timestamp. In this case, the greatest
19 // value is retained and used to re-compute the average. Therefore, the values
20 // provided to this class' methods should be appropriately translated with this
21 // in mind. For example, an "fraction available" metric should be translated
22 // into a "fraction utilized" one.
23 //
24 // Usage note: Reset() must be called at least once before the first call to
25 // Update().
26 //
27 // This template class supports data points that are timestamped using either
28 // |base::TimeDelta| or |base::TimeTicks|.
29 template <typename TimeType>
30 class FeedbackSignalAccumulator {
31 public:
32 // |half_life| is the amount of time that must pass between two data points to
33 // move the accumulated average value halfway in-between. Example: If
34 // |half_life| is one second, then calling Reset(0.0, t=0s) and then
35 // Update(1.0, t=1s) will result in an accumulated average value of 0.5.
36 explicit FeedbackSignalAccumulator(base::TimeDelta half_life)
37 : half_life_(half_life), average_(NAN) {
38 DCHECK(half_life_ > base::TimeDelta());
39 }
40
41 // Erase all memory of historical values, re-starting with the given
42 // |starting_value|.
43 void Reset(double starting_value, TimeType timestamp) {
44 average_ = update_value_ = prior_average_ = starting_value;
45 reset_time_ = update_time_ = prior_update_time_ = timestamp;
46 }
47
48 TimeType reset_time() const { return reset_time_; }
49
50 // Apply the given |value|, which was observed at the given |timestamp|, to
51 // the accumulated average. If the timestamp is in chronological order, the
52 // update succeeds and this method returns true. Otherwise the update has no
53 // effect and false is returned. If there are two or more updates at the same
54 // |timestamp|, only the one with the greatest value will be accounted for
55 // (see class comments for elaboration).
56 bool Update(double value, TimeType timestamp) {
57 DCHECK(!std::isnan(average_)) << "Reset() must be called once.";
58
59 if (timestamp < update_time_) {
60 return false; // Not in chronological order.
61 } else if (timestamp == update_time_) {
62 if (timestamp == reset_time_) {
63 // Edge case: Multiple updates at reset timestamp.
64 average_ = update_value_ = prior_average_ =
65 std::max(value, update_value_);
66 return true;
67 }
68 if (value <= update_value_)
69 return true;
70 update_value_ = value;
71 } else {
72 prior_average_ = average_;
73 prior_update_time_ = update_time_;
74 update_value_ = value;
75 update_time_ = timestamp;
76 }
77
78 const double elapsed_us = static_cast<double>(
79 (update_time_ - prior_update_time_).InMicroseconds());
80 const double weight =
81 elapsed_us / (elapsed_us + half_life_.InMicroseconds());
82 average_ = weight * update_value_ + (1.0 - weight) * prior_average_;
83 DCHECK(std::isfinite(average_));
84
85 return true;
86 }
87
88 TimeType update_time() const { return update_time_; }
89
90 // Returns the current accumulated average value.
91 double current() const { return average_; }
92
93 private:
94 // In conjunction with the |update_time_| and |prior_update_time_|, this is
95 // used to compute the weight of the current update value versus the prior
96 // accumulated average.
97 const base::TimeDelta half_life_;
98
99 TimeType reset_time_; // |timestamp| passed in last call to Reset().
100 double average_; // Current accumulated average.
101 double update_value_; // Latest |value| accepted by Update().
102 TimeType update_time_; // Latest |timestamp| accepted by Update().
103 double prior_average_; // Accumulated average before last call to Update().
104 TimeType prior_update_time_; // |timestamp| in prior call to Update().
105 };
106
107 } // namespace media
108
109 #endif // MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_
OLDNEW
« no previous file with comments | « media/capture/capture.gyp ('k') | media/capture/content/feedback_signal_accumulator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698