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

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

Issue 1021943002: Introduce cadence based VideoRendererAlgorithm. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improve EffectiveFramesQueued. Created 5 years, 8 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 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 #include "media/filters/video_cadence_estimator.h"
6
7 #include <algorithm>
8 #include <limits>
9
10 namespace media {
11
12 VideoCadenceEstimator::VideoCadenceEstimator(
13 base::TimeDelta minimum_time_until_glitch)
14 : cadence_hysteresis_enabled_(true),
15 minimum_time_until_glitch_(minimum_time_until_glitch) {
16 Reset();
17 }
18
19 VideoCadenceEstimator::~VideoCadenceEstimator() {
20 }
21
22 void VideoCadenceEstimator::Reset() {
23 cadence_ = fractional_cadence_ = 0;
24 previous_cadence_ = previous_fractional_cadence_ = 0;
25 render_intervals_cadence_held_ = 0;
26 }
27
28 bool VideoCadenceEstimator::UpdateCadenceEstimate(
29 base::TimeDelta render_interval,
30 base::TimeDelta frame_duration,
31 base::TimeDelta max_acceptable_drift) {
32 base::TimeDelta time_until_cadence_glitch;
33 base::TimeDelta time_until_fractional_cadence_glitch;
34
35 // See if the clamped cadence fits acceptable thresholds for exhausting drift.
36 int new_cadence = 0, new_fractional_cadence = 0;
37 if (CalculateCadence(render_interval, frame_duration, max_acceptable_drift,
38 false, &new_cadence, &time_until_cadence_glitch)) {
39 } else if (CalculateCadence(render_interval, frame_duration,
40 max_acceptable_drift, true,
41 &new_fractional_cadence,
42 &time_until_fractional_cadence_glitch)) {
43 new_cadence = 1;
44 }
45
46 // Nothing changed, so do nothing.
47 if (new_cadence == cadence_ &&
48 new_fractional_cadence == fractional_cadence_) {
49 render_intervals_cadence_held_ = 0;
50 return false;
51 }
52
53 if (!cadence_hysteresis_enabled_) {
54 cadence_ = new_cadence;
55 fractional_cadence_ = new_fractional_cadence;
56 return true;
57 }
58
59 // Wait until enough render intervals have elapsed before accepting the
60 // cadence change. Prevents oscillation of the cadence selection.
61 if (new_cadence == previous_cadence_ &&
62 new_fractional_cadence == previous_fractional_cadence_) {
63 if (++render_intervals_cadence_held_ * render_interval >=
64 base::TimeDelta::FromMilliseconds(kMinimumCadenceDurationMs)) {
65 DVLOG(1) << "Cadence switch: (" << cadence_ << ", " << fractional_cadence_
66 << ") -> (" << new_cadence << ", " << new_fractional_cadence
67 << ") :: (" << time_until_cadence_glitch << ", "
68 << time_until_fractional_cadence_glitch << ")";
69
70 cadence_ = new_cadence;
71 fractional_cadence_ = new_fractional_cadence;
72 return true;
73 } else {
74 DVLOG(2) << "Hysteresis prevented cadence switch: (" << cadence_ << ", "
75 << fractional_cadence_ << ") -> (" << new_cadence << ", "
76 << new_fractional_cadence << ") :: ("
77 << time_until_cadence_glitch << ", "
78 << time_until_fractional_cadence_glitch << ")";
79 }
80 } else {
81 previous_cadence_ = new_cadence;
82 previous_fractional_cadence_ = new_fractional_cadence;
83 render_intervals_cadence_held_ = 1;
84 }
85
86 return false;
87 }
88
89 bool VideoCadenceEstimator::CalculateCadence(
90 base::TimeDelta render_interval,
91 base::TimeDelta frame_duration,
92 base::TimeDelta max_acceptable_drift,
93 bool fractional,
94 int* cadence,
95 base::TimeDelta* time_until_glitch) {
96 *cadence = 0;
97 *time_until_glitch = base::TimeDelta();
98
99 // The perfect cadence is the number of render intervals per frame, while the
100 // clamped cadence is the nearest matching integer cadence.
101 //
102 // Fractional cadence is checked to see if we have a cadence which would look
103 // best if we consistently drop the same frames.
104 //
105 // As mentioned in the introduction, |perfect_cadence| is the ratio of the
106 // frame duration to render interval length; while |clamped_cadence| is the
107 // nearest integer value to |perfect_cadence|. When computing a fractional
108 // cadence (1/|perfect_cadence|), |fractional| must be set to true to ensure
109 // the rendered and actual frame durations are computed correctly.
110 const double perfect_cadence =
111 fractional ? render_interval.InSecondsF() / frame_duration.InSecondsF()
112 : frame_duration.InSecondsF() / render_interval.InSecondsF();
113 const int clamped_cadence = perfect_cadence + 0.5;
114 if (clamped_cadence == 0.0)
115 return false;
116
117 // Calculate the drift in microseconds for each frame we render at cadence
118 // instead of for its real duration.
119 const base::TimeDelta rendered_frame_duration =
120 fractional ? render_interval : clamped_cadence * render_interval;
121
122 // When computing a fractional drift, we render the first of |clamped_cadence|
123 // frames and drop |clamped_cadence| - 1 frames. To make the calculations
124 // below work we need to project out the timestamp of the frame which would be
125 // rendered after accounting for those |clamped_cadence| frames.
126 const base::TimeDelta actual_frame_duration =
127 fractional ? clamped_cadence * frame_duration : frame_duration;
128 if (rendered_frame_duration == actual_frame_duration) {
129 *cadence = clamped_cadence;
130 return true;
131 }
132
133 // Compute how long it'll take to exhaust the drift using |clamped_cadence|.
134 const double duration_delta = std::abs(
135 (rendered_frame_duration - actual_frame_duration).InMicroseconds());
136 const int64 frames_until_drift_exhausted =
137 std::ceil(max_acceptable_drift.InMicroseconds() / duration_delta);
138 *time_until_glitch = rendered_frame_duration * frames_until_drift_exhausted;
139
140 if (*time_until_glitch >= minimum_time_until_glitch_) {
141 *cadence = clamped_cadence;
142 return true;
143 }
144
145 return false;
146 }
147
148 int VideoCadenceEstimator::GetCadenceForFrame(int index) const {
149 DCHECK(has_cadence());
150 DCHECK_GE(index, 0);
151
152 if (fractional_cadence_)
153 return index % fractional_cadence_ == 0 ? 1 : 0;
154
155 return cadence_;
156 }
157
158 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698