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

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

Issue 1459923003: Fix Bug: Video with Variable Frame Rate plays at incorrect speed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/video_cadence_estimator.h" 5 #include "media/filters/video_cadence_estimator.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <iterator> 9 #include <iterator>
10 #include <limits> 10 #include <limits>
11 #include <string> 11 #include <string>
12 12
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 14
15 namespace media { 15 namespace media {
16 16
17 // To prevent oscillation in and out of cadence or between cadence values, we 17 // To prevent oscillation in and out of cadence or between cadence values, we
18 // require some time to elapse before a cadence switch is accepted. 18 // require some time to elapse before a cadence switch is accepted.
19 const int kMinimumCadenceDurationMs = 100; 19 const int kMinimumCadenceDurationMs = 100;
20 20
21 // The numbers are used to decide whether the current video is variable FPS or
22 // constant FPS. If ratio of the sample deviation and the sample average is
23 // above |kVariableFPSFactor|, then it is recognized as a variable FPS, and if
24 // the ratio is below |kConstantFPSFactor|, then it is recognized as a constant
25 // FPS, and if the ratio is in between the two factors, then we do not change
26 // previous recognition.
27 const double kVariableFPSFactor = 0.1;
DaleCurtis 2015/11/20 23:50:46 Your variable frame rate clip was 0.7? If so it se
qiangchen 2015/11/25 18:06:33 Simply excluding that extreme case may not be opti
DaleCurtis 2015/11/25 21:29:24 Sure, but I think we want to err on the side of ca
qiangchen 2015/12/01 19:37:53 Done.
28 const double kConstantFPSFactor = 0.07;
29
21 // Records the number of cadence changes to UMA. 30 // Records the number of cadence changes to UMA.
22 static void HistogramCadenceChangeCount(int cadence_changes) { 31 static void HistogramCadenceChangeCount(int cadence_changes) {
23 const int kCadenceChangeMax = 10; 32 const int kCadenceChangeMax = 10;
24 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.VideoRenderer.CadenceChanges", 33 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.VideoRenderer.CadenceChanges",
25 cadence_changes, 0, kCadenceChangeMax, 34 cadence_changes, 0, kCadenceChangeMax,
26 kCadenceChangeMax); 35 kCadenceChangeMax);
27 } 36 }
28 37
29 // Construct a Cadence vector, a vector of integers satisfying the following 38 // Construct a Cadence vector, a vector of integers satisfying the following
30 // conditions: 39 // conditions:
(...skipping 28 matching lines...) Expand all
59 actual_accumulate += output[i] * n; 68 actual_accumulate += output[i] * n;
60 } 69 }
61 70
62 return output; 71 return output;
63 } 72 }
64 73
65 VideoCadenceEstimator::VideoCadenceEstimator( 74 VideoCadenceEstimator::VideoCadenceEstimator(
66 base::TimeDelta minimum_time_until_max_drift) 75 base::TimeDelta minimum_time_until_max_drift)
67 : cadence_hysteresis_threshold_( 76 : cadence_hysteresis_threshold_(
68 base::TimeDelta::FromMilliseconds(kMinimumCadenceDurationMs)), 77 base::TimeDelta::FromMilliseconds(kMinimumCadenceDurationMs)),
69 minimum_time_until_max_drift_(minimum_time_until_max_drift) { 78 minimum_time_until_max_drift_(minimum_time_until_max_drift),
79 is_variable_frame_rate_(false) {
70 Reset(); 80 Reset();
71 } 81 }
72 82
73 VideoCadenceEstimator::~VideoCadenceEstimator() { 83 VideoCadenceEstimator::~VideoCadenceEstimator() {
74 } 84 }
75 85
76 void VideoCadenceEstimator::Reset() { 86 void VideoCadenceEstimator::Reset() {
77 cadence_.clear(); 87 cadence_.clear();
78 pending_cadence_.clear(); 88 pending_cadence_.clear();
79 cadence_changes_ = render_intervals_cadence_held_ = 0; 89 cadence_changes_ = render_intervals_cadence_held_ = 0;
80 first_update_call_ = true; 90 first_update_call_ = true;
81 } 91 }
82 92
83 bool VideoCadenceEstimator::UpdateCadenceEstimate( 93 bool VideoCadenceEstimator::UpdateCadenceEstimate(
84 base::TimeDelta render_interval, 94 base::TimeDelta render_interval,
85 base::TimeDelta frame_duration, 95 base::TimeDelta frame_duration,
96 base::TimeDelta frame_duration_deviation,
86 base::TimeDelta max_acceptable_drift) { 97 base::TimeDelta max_acceptable_drift) {
87 DCHECK_GT(render_interval, base::TimeDelta()); 98 DCHECK_GT(render_interval, base::TimeDelta());
88 DCHECK_GT(frame_duration, base::TimeDelta()); 99 DCHECK_GT(frame_duration, base::TimeDelta());
89 100
101 if (frame_duration_deviation.InMillisecondsF() >
102 kVariableFPSFactor * frame_duration.InMillisecondsF()) {
103 is_variable_frame_rate_ = true;
104 } else if (frame_duration_deviation.InMillisecondsF() <
105 kConstantFPSFactor * frame_duration.InMillisecondsF()) {
106 is_variable_frame_rate_ = false;
107 }
108
109 // Variable FPS detected, turn off Cadence by force.
110 if (is_variable_frame_rate_) {
111 render_intervals_cadence_held_ = 0;
112 if (cadence_ != Cadence()) {
DaleCurtis 2015/11/20 23:50:46 if !cadence_.empty() cadence_.clear()
qiangchen 2015/11/25 18:06:33 Done.
113 cadence_ = Cadence();
114 return true;
115 }
116 return false;
117 }
118
90 base::TimeDelta time_until_max_drift; 119 base::TimeDelta time_until_max_drift;
91 120
92 // See if we can find a cadence which fits the data. 121 // See if we can find a cadence which fits the data.
93 Cadence new_cadence = 122 Cadence new_cadence =
94 CalculateCadence(render_interval, frame_duration, max_acceptable_drift, 123 CalculateCadence(render_interval, frame_duration, max_acceptable_drift,
95 &time_until_max_drift); 124 &time_until_max_drift);
96 125
97 // If this is the first time UpdateCadenceEstimate() has been called, 126 // If this is the first time UpdateCadenceEstimate() has been called,
98 // initialize the histogram with a zero count for cadence changes; this 127 // initialize the histogram with a zero count for cadence changes; this
99 // allows us to track the number of playbacks which have cadence at all. 128 // allows us to track the number of playbacks which have cadence at all.
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 254
226 std::ostringstream os; 255 std::ostringstream os;
227 os << "["; 256 os << "[";
228 std::copy(cadence.begin(), cadence.end() - 1, 257 std::copy(cadence.begin(), cadence.end() - 1,
229 std::ostream_iterator<int>(os, ":")); 258 std::ostream_iterator<int>(os, ":"));
230 os << cadence.back() << "]"; 259 os << cadence.back() << "]";
231 return os.str(); 260 return os.str();
232 } 261 }
233 262
234 } // namespace media 263 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698