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

Side by Side Diff: media/filters/video_cadence_estimator.h

Issue 1021943002: Introduce cadence based VideoRendererAlgorithm. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix evaluation order. Created 5 years, 7 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
« no previous file with comments | « media/base/moving_average_unittest.cc ('k') | media/filters/video_cadence_estimator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 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_FILTERS_VIDEO_CADENCE_ESTIMATOR_H_
6 #define MEDIA_FILTERS_VIDEO_CADENCE_ESTIMATOR_H_
7
8 #include "base/time/time.h"
9 #include "media/base/media_export.h"
10
11 namespace media {
12
13 // Estimates whether a given frame duration and render interval length have a
14 // render cadence which would allow for optimal uniformity of displayed frame
15 // durations over time.
16 //
17 // Cadence is the ratio of the frame duration to render interval length. I.e.
18 // for 30fps in 60Hz the cadence would be (1/30) / (1/60) = 60 / 30 = 2. It's
19 // common that this is not an exact integer, e.g., 29.974fps in 60Hz which
20 // would have a cadence of (1/29.974) / (1/60) = ~2.0029.
21 //
22 // Clamped integer cadence means we round the actual cadence (~2.0029 in the
23 // pending example) to the nearest integer value (2 in this case). If the
24 // delta between those values is small, we can choose to render frames for the
25 // integer number of render intervals; shortening or lengthening the actual
26 // rendered frame duration. Doing so ensures each frame gets an optimal amount
27 // of display time.
28 //
29 // Obviously clamping cadence like that leads to drift over time of the actual
30 // VideoFrame timestamp relative to its rendered time, so we perform some
31 // calculations to ensure we only clamp cadence when it will take some time to
32 // drift an undesirable amount; see CalculateCadence() for details on how this
33 // calculation is made.
34 //
35 // Notably, this concept can be extended to include fractional cadence when the
36 // frame duration is shorter than the render interval; e.g. 120fps in 60Hz. In
37 // this case, the first frame in each group of N frames is displayed once, while
38 // the next N - 1 frames are dropped; where N is the fractional cadence of the
39 // frame group. Using the pending example N = 120/60 = 2. See implementations
40 // of CalculateCadence() and UpdateCadenceEstimate() for more details.
41 //
42 // In practice this works out to the following for common setups if we use
43 // cadence based selection:
44 //
45 // 29.5fps in 60Hz, ~17ms max drift => exhausted in ~1 second.
46 // 29.9fps in 60Hz, ~17ms max drift => exhausted in ~16.4 seconds.
47 // 24fps in 60Hz, ~21ms max drift => exhausted in ~0.15 seconds.
48 // 25fps in 60Hz, 20ms max drift => exhausted in ~4.0 seconds.
49 // 59.9fps in 60Hz, ~8.3ms max drift => exhausted in ~8.2 seconds.
50 // 24.9fps in 50Hz, ~20ms max drift => exhausted in ~20.5 seconds.
51 // 120fps in 59.9Hz, ~8.3ms max drift => exhausted in ~8.2 seconds.
52 //
53 class MEDIA_EXPORT VideoCadenceEstimator {
54 public:
55 // As mentioned in the introduction, the determination of whether to clamp to
56 // a given cadence is based on how long it takes before a frame would have to
57 // be dropped or repeated to compensate for reaching the maximum acceptable
58 // drift; this time length is controlled by |minimum_time_until_glitch|.
59 explicit VideoCadenceEstimator(base::TimeDelta minimum_time_until_glitch);
60 ~VideoCadenceEstimator();
61
62 // Clears stored cadence information.
63 void Reset();
64
65 // Updates the estimates for |cadence_| and |fractional_cadence_| based on the
66 // given values as described in the introduction above.
67 //
68 // Clients should call this and then update the cadence for all frames via the
69 // GetCadenceForFrame() method.
70 //
71 // Cadence changes will not take affect until enough render intervals have
72 // elapsed. For the purposes of hysteresis, each UpdateCadenceEstimate() call
73 // is assumed to elapse one |render_interval| worth of time.
74 //
75 // Returns true if the cadence has changed since the last call.
76 bool UpdateCadenceEstimate(base::TimeDelta render_interval,
77 base::TimeDelta frame_duration,
78 base::TimeDelta max_acceptable_drift);
79
80 // Returns true if a useful cadence was found.
81 bool has_cadence() const { return cadence_ > 0; }
82
83 // Given a frame |index|, where zero is the most recently rendered frame,
84 // returns the ideal cadence for that frame.
85 int GetCadenceForFrame(int index) const;
86
87 void set_cadence_hysteresis_threshold_for_testing(base::TimeDelta threshold) {
88 cadence_hysteresis_threshold_ = threshold;
89 }
90
91 int get_cadence_for_testing() const {
92 return cadence_ && fractional_cadence_ ? fractional_cadence_ : cadence_;
93 }
94
95 private:
96 // Calculates the clamped cadence for the given |render_interval| and
97 // |frame_duration|, then calculates how long that cadence can be used before
98 // exhausting |max_acceptable_drift|. If the time until exhaustion is greater
99 // than |minimum_time_until_glitch_|, returns true and sets |cadence| to the
100 // clamped cadence. If the clamped cadence is unusable, |cadence| will be set
101 // to zero.
102 //
103 // If |fractional| is true, GetCadence() will calculate the clamped cadence
104 // using the ratio of the |render_interval| to |frame_duration| instead of
105 // vice versa.
106 //
107 // Sets |time_until_glitch| to the computed glitch time. Set to zero if the
108 // clamped cadence is unusable.
109 bool CalculateCadence(base::TimeDelta render_interval,
110 base::TimeDelta frame_duration,
111 base::TimeDelta max_acceptable_drift,
112 bool fractional,
113 int* cadence,
114 base::TimeDelta* time_until_glitch);
115
116 // The idealized cadence for all frames seen thus far; updated based upon the
117 // ratio of |frame_duration| to |render_interval|, or vice versa, as given to
118 // UpdateCadenceEstimate(). Zero if no integer cadence could be detected.
119 //
120 // Fractional cadences are handled by strongly preferring the first frame in
121 // a series if it fits within acceptable drift. E.g., with 120fps content on
122 // a 60Hz monitor we'll strongly prefer the first frame of every 2 frames.
123 //
124 // |fractional_cadence_| is the number of frames per render interval; the
125 // first of which would be rendered and the rest dropped.
126 int cadence_;
127 int fractional_cadence_;
128
129 // Used as hysteresis to prevent oscillation between cadence and coverage
130 // based rendering methods. Pending values are updated upon each new cadence
131 // detected by UpdateCadenceEstimate().
132 //
133 // Once a new cadence is detected, |render_intervals_cadence_held_| is
134 // incremented for each UpdateCadenceEstimate() call where the cadence matches
135 // one of the pending values. |render_intervals_cadence_held_| is cleared
136 // when a "new" cadence matches |cadence_| or |pending_cadence_|.
137 //
138 // Once |kMinimumCadenceDurationMs| is exceeded in render intervals, the
139 // detected cadence is set in |cadence_| and |fractional_cadence_|.
140 int pending_cadence_;
141 int pending_fractional_cadence_;
142 int render_intervals_cadence_held_;
143 base::TimeDelta cadence_hysteresis_threshold_;
144
145 // The minimum amount of time allowed before a glitch occurs before confirming
146 // cadence for a given render interval and frame duration.
147 const base::TimeDelta minimum_time_until_glitch_;
148
149 DISALLOW_COPY_AND_ASSIGN(VideoCadenceEstimator);
150 };
151
152 } // namespace media
153
154 #endif // MEDIA_FILTERS_VIDEO_CADENCE_ESTIMATOR_H_
OLDNEW
« no previous file with comments | « media/base/moving_average_unittest.cc ('k') | media/filters/video_cadence_estimator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698