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

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: Fix frame expiration when Render() never called. 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
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 DCHECK_GT(render_interval, base::TimeDelta());
33 DCHECK_GT(frame_duration, base::TimeDelta());
34
35 base::TimeDelta time_until_cadence_glitch;
36 base::TimeDelta time_until_fractional_cadence_glitch;
xhwang 2015/04/28 16:01:08 It seems these two are only for logging? Can we ju
DaleCurtis 2015/04/28 21:45:24 No, because we need both values for the log messag
xhwang 2015/04/28 22:17:39 Acknowledged.
37
38 // See if the clamped cadence fits acceptable thresholds for exhausting drift.
39 int new_cadence = 0, new_fractional_cadence = 0;
40 if (CalculateCadence(render_interval, frame_duration, max_acceptable_drift,
41 false, &new_cadence, &time_until_cadence_glitch)) {
xhwang 2015/04/28 16:01:08 DCHECK(new_cadence)?
DaleCurtis 2015/04/28 21:45:24 Done.
42 } else if (CalculateCadence(render_interval, frame_duration,
43 max_acceptable_drift, true,
44 &new_fractional_cadence,
45 &time_until_fractional_cadence_glitch)) {
46 new_cadence = 1;
47 }
48
49 // Nothing changed, so do nothing.
50 if (new_cadence == cadence_ &&
51 new_fractional_cadence == fractional_cadence_) {
52 render_intervals_cadence_held_ = 0;
xhwang 2015/04/28 16:01:08 The comment says 132 // ... |render_intervals
DaleCurtis 2015/04/28 21:45:24 This prevents the previous cadence values from acc
53 return false;
54 }
55
56 if (!cadence_hysteresis_enabled_) {
57 cadence_ = new_cadence;
58 fractional_cadence_ = new_fractional_cadence;
59 return true;
60 }
61
62 // Wait until enough render intervals have elapsed before accepting the
63 // cadence change. Prevents oscillation of the cadence selection.
64 if (new_cadence == previous_cadence_ &&
xhwang 2015/04/28 16:01:08 |previous_cadence| is really a |pending_cadence_|
DaleCurtis 2015/04/28 21:45:24 Done.
65 new_fractional_cadence == previous_fractional_cadence_) {
66 if (++render_intervals_cadence_held_ * render_interval >=
xhwang 2015/04/28 16:01:08 note: render_interval can be different every time
DaleCurtis 2015/04/28 21:45:24 Yup.
67 base::TimeDelta::FromMilliseconds(kMinimumCadenceDurationMs)) {
68 DVLOG(1) << "Cadence switch: (" << cadence_ << ", " << fractional_cadence_
69 << ") -> (" << new_cadence << ", " << new_fractional_cadence
70 << ") :: (" << time_until_cadence_glitch << ", "
71 << time_until_fractional_cadence_glitch << ")";
72
73 cadence_ = new_cadence;
74 fractional_cadence_ = new_fractional_cadence;
75 return true;
76 } else {
77 DVLOG(2) << "Hysteresis prevented cadence switch: (" << cadence_ << ", "
78 << fractional_cadence_ << ") -> (" << new_cadence << ", "
79 << new_fractional_cadence << ") :: ("
80 << time_until_cadence_glitch << ", "
81 << time_until_fractional_cadence_glitch << ")";
xhwang 2015/04/28 16:01:08 nit: just return false here, so that you don't nee
DaleCurtis 2015/04/28 21:45:24 Done.
82 }
83 } else {
84 previous_cadence_ = new_cadence;
85 previous_fractional_cadence_ = new_fractional_cadence;
86 render_intervals_cadence_held_ = 1;
xhwang 2015/04/28 16:01:08 If in the extreme case where cadence estimation os
DaleCurtis 2015/04/28 21:45:24 2.5 is pretty unlikely to clamp to 2 or 3, it exha
xhwang 2015/04/28 22:17:39 Acknowledged.
87 }
88
89 return false;
90 }
91
92 bool VideoCadenceEstimator::CalculateCadence(
93 base::TimeDelta render_interval,
94 base::TimeDelta frame_duration,
95 base::TimeDelta max_acceptable_drift,
96 bool fractional,
97 int* cadence,
98 base::TimeDelta* time_until_glitch) {
99 *cadence = 0;
100 *time_until_glitch = base::TimeDelta();
xhwang 2015/04/28 16:01:08 DCHECK instead of set?
DaleCurtis 2015/04/28 21:45:24 No, I want to clear them every time.
xhwang 2015/04/28 22:17:39 hmm, wondering why? The caller already initializes
DaleCurtis 2015/04/29 00:11:12 Actually, they don't need to be initialized here a
101
102 // The perfect cadence is the number of render intervals per frame, while the
103 // clamped cadence is the nearest matching integer cadence.
104 //
105 // Fractional cadence is checked to see if we have a cadence which would look
106 // best if we consistently drop the same frames.
107 //
108 // As mentioned in the introduction, |perfect_cadence| is the ratio of the
109 // frame duration to render interval length; while |clamped_cadence| is the
110 // nearest integer value to |perfect_cadence|. When computing a fractional
111 // cadence (1/|perfect_cadence|), |fractional| must be set to true to ensure
112 // the rendered and actual frame durations are computed correctly.
113 const double perfect_cadence =
114 fractional ? render_interval.InSecondsF() / frame_duration.InSecondsF()
115 : frame_duration.InSecondsF() / render_interval.InSecondsF();
116 const int clamped_cadence = perfect_cadence + 0.5;
117 if (!clamped_cadence)
118 return false;
119
120 // Calculate the drift in microseconds for each frame we render at cadence
121 // instead of for its real duration.
122 const base::TimeDelta rendered_frame_duration =
123 fractional ? render_interval : clamped_cadence * render_interval;
124
125 // When computing a fractional drift, we render the first of |clamped_cadence|
126 // frames and drop |clamped_cadence| - 1 frames. To make the calculations
127 // below work we need to project out the timestamp of the frame which would be
128 // rendered after accounting for those |clamped_cadence| frames.
xhwang 2015/04/28 16:01:08 We are checking "fractional ?" in 3 places in this
DaleCurtis 2015/04/28 21:45:24 The math is already tricky, I'd rather not duplica
xhwang 2015/04/28 22:17:39 For me I have to read this function twice, one wit
DaleCurtis 2015/04/29 00:11:11 l.136, l.148 would end up in a third function with
129 const base::TimeDelta actual_frame_duration =
130 fractional ? clamped_cadence * frame_duration : frame_duration;
131 if (rendered_frame_duration == actual_frame_duration) {
132 *cadence = clamped_cadence;
133 return true;
134 }
135
136 // Compute how long it'll take to exhaust the drift using |clamped_cadence|.
137 const double duration_delta = std::abs(
138 (rendered_frame_duration - actual_frame_duration).InMicroseconds());
139 const int64 frames_until_drift_exhausted =
140 std::ceil(max_acceptable_drift.InMicroseconds() / duration_delta);
141 *time_until_glitch = rendered_frame_duration * frames_until_drift_exhausted;
142
143 if (*time_until_glitch >= minimum_time_until_glitch_) {
144 *cadence = clamped_cadence;
145 return true;
146 }
147
148 return false;
149 }
150
151 int VideoCadenceEstimator::GetCadenceForFrame(int index) const {
152 DCHECK(has_cadence());
153 DCHECK_GE(index, 0);
154
155 if (fractional_cadence_)
156 return index % fractional_cadence_ == 0 ? 1 : 0;
157
158 return cadence_;
159 }
160
161 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698