Chromium Code Reviews

Side by Side Diff: mojo/services/media/common/cpp/timeline_rate.cc

Issue 1952673003: Motown: Rename Ratio and LinearFunction classes (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 <limits> 5 #include <limits>
6 #include <utility> 6 #include <utility>
7 7
8 #include "mojo/public/cpp/environment/logging.h" 8 #include "mojo/public/cpp/environment/logging.h"
9 #include "mojo/services/media/common/cpp/ratio.h" 9 #include "mojo/services/media/common/cpp/timeline_rate.h"
10 10
11 namespace mojo { 11 namespace mojo {
12 namespace media { 12 namespace media {
13 13
14 namespace { 14 namespace {
15 15
16 // Calculates the greatest common denominator (factor) of two values. 16 // Calculates the greatest common denominator (factor) of two values.
17 template <typename T> 17 template <typename T>
18 T BinaryGcd(T a, T b) { 18 T BinaryGcd(T a, T b) {
19 if (a == 0) { 19 if (a == 0) {
(...skipping 29 matching lines...)
49 std::swap(a, b); 49 std::swap(a, b);
50 } 50 }
51 51
52 b = b - a; 52 b = b - a;
53 } while (b != 0); 53 } while (b != 0);
54 54
55 // Multiply in the common factors of two. 55 // Multiply in the common factors of two.
56 return a << twos; 56 return a << twos;
57 } 57 }
58 58
59 // Reduces the ration of *numerator and *denominator. 59 // Reduces the ratio of *numerator and *denominator.
60 template <typename T> 60 template <typename T>
61 void ReduceRatio(T* numerator, T* denominator) { 61 void ReduceRatio(T* numerator, T* denominator) {
62 MOJO_DCHECK(numerator != nullptr); 62 MOJO_DCHECK(numerator != nullptr);
63 MOJO_DCHECK(denominator != nullptr); 63 MOJO_DCHECK(denominator != nullptr);
64 MOJO_DCHECK(*denominator != 0); 64 MOJO_DCHECK(*denominator != 0);
65 65
66 T gcd = BinaryGcd(*numerator, *denominator); 66 T gcd = BinaryGcd(*numerator, *denominator);
67 67
68 if (gcd == 0) { 68 if (gcd == 0) {
69 *denominator = 1; 69 *denominator = 1;
70 return; 70 return;
71 } 71 }
72 72
73 if (gcd == 1) { 73 if (gcd == 1) {
74 return; 74 return;
75 } 75 }
76 76
77 *numerator = *numerator / gcd; 77 *numerator = *numerator / gcd;
78 *denominator = *denominator / gcd; 78 *denominator = *denominator / gcd;
79 } 79 }
80 80
81 template void ReduceRatio<uint64_t>(uint64_t* numerator, uint64_t* denominator); 81 template void ReduceRatio<uint64_t>(uint64_t* numerator, uint64_t* denominator);
82 template void ReduceRatio<uint32_t>(uint32_t* numerator, uint32_t* denominator); 82 template void ReduceRatio<uint32_t>(uint32_t* numerator, uint32_t* denominator);
83 83
84 // Scales a uint64_t value by the ratio of two uint32_t values. If round_up is 84 // Scales a uint64_t value by the ratio of two uint32_t values. If round_up is
85 // true, the result is rounded up rather than down. overflow is set to indicate 85 // true, the result is rounded up rather than down. overflow is set to indicate
86 // overflow. 86 // overflow.
87 uint64_t ScaleUInt64(uint64_t value, 87 uint64_t ScaleUInt64(uint64_t value,
88 uint32_t numerator, 88 uint32_t subject_delta,
89 uint32_t denominator, 89 uint32_t reference_delta,
90 bool round_up, 90 bool round_up,
91 bool* overflow) { 91 bool* overflow) {
92 MOJO_DCHECK(denominator != 0u); 92 MOJO_DCHECK(reference_delta != 0u);
93 MOJO_DCHECK(overflow != nullptr); 93 MOJO_DCHECK(overflow != nullptr);
94 94
95 constexpr uint64_t kLow32Bits = 0xffffffffu; 95 constexpr uint64_t kLow32Bits = 0xffffffffu;
96 constexpr uint64_t kHigh32Bits = kLow32Bits << 32u; 96 constexpr uint64_t kHigh32Bits = kLow32Bits << 32u;
97 97
98 // high and low are the product of the numerator and the high and low halves 98 // high and low are the product of the subject_delta and the high and low
99 // halves
99 // (respectively) of value. 100 // (respectively) of value.
100 uint64_t high = numerator * (value >> 32u); 101 uint64_t high = subject_delta * (value >> 32u);
101 uint64_t low = numerator * (value & kLow32Bits); 102 uint64_t low = subject_delta * (value & kLow32Bits);
102 // Ignoring overflow and remainder, the result we want is: 103 // Ignoring overflow and remainder, the result we want is:
103 // ((high << 32) + low) / denominator. 104 // ((high << 32) + low) / reference_delta.
104 105
105 // Move the high end of low into the low end of high. 106 // Move the high end of low into the low end of high.
106 high += low >> 32u; 107 high += low >> 32u;
107 low = low & kLow32Bits; 108 low = low & kLow32Bits;
108 // Ignoring overflow and remainder, the result we want is still: 109 // Ignoring overflow and remainder, the result we want is still:
109 // ((high << 32) + low) / denominator. 110 // ((high << 32) + low) / reference_delta.
110 111
111 // When we divide high by denominator, there'll be a remainder. Make 112 // When we divide high by reference_delta, there'll be a remainder. Make
112 // that the high end of low, which is currently all zeroes. 113 // that the high end of low, which is currently all zeroes.
113 low |= (high % denominator) << 32u; 114 low |= (high % reference_delta) << 32u;
114 115
115 // Determine if we need to round up when we're done: 116 // Determine if we need to round up when we're done:
116 round_up = round_up && (low % denominator) != 0; 117 round_up = round_up && (low % reference_delta) != 0;
117 118
118 // Do the division. 119 // Do the division.
119 high /= denominator; 120 high /= reference_delta;
120 low /= denominator; 121 low /= reference_delta;
121 122
122 // If high's top 32 bits aren't all zero, we have overflow. 123 // If high's top 32 bits aren't all zero, we have overflow.
123 if (high & kHigh32Bits) { 124 if (high & kHigh32Bits) {
124 *overflow = true; 125 *overflow = true;
125 return 0; 126 return 0;
126 } 127 }
127 128
128 uint64_t result = (high << 32u) | low; 129 uint64_t result = (high << 32u) | low;
129 if (round_up) { 130 if (round_up) {
130 if (result == std::numeric_limits<int64_t>::max()) { 131 if (result == std::numeric_limits<int64_t>::max()) {
131 *overflow = true; 132 *overflow = true;
132 return 0; 133 return 0;
133 } 134 }
134 ++result; 135 ++result;
135 } 136 }
136 137
137 *overflow = false; 138 *overflow = false;
138 return result; 139 return result;
139 } 140 }
140 141
141 } // namespace 142 } // namespace
142 143
143 // static 144 // static
144 void Ratio::Reduce(uint32_t* numerator, uint32_t* denominator) { 145 void TimelineRate::Reduce(uint32_t* subject_delta, uint32_t* reference_delta) {
145 ReduceRatio(numerator, denominator); 146 ReduceRatio(subject_delta, reference_delta);
146 } 147 }
147 148
148 // static 149 // static
149 void Ratio::Product(uint32_t a_numerator, 150 void TimelineRate::Product(uint32_t a_subject_delta,
150 uint32_t a_denominator, 151 uint32_t a_reference_delta,
151 uint32_t b_numerator, 152 uint32_t b_subject_delta,
152 uint32_t b_denominator, 153 uint32_t b_reference_delta,
153 uint32_t* product_numerator, 154 uint32_t* product_subject_delta,
154 uint32_t* product_denominator, 155 uint32_t* product_reference_delta,
155 bool exact) { 156 bool exact) {
156 MOJO_DCHECK(a_denominator != 0); 157 MOJO_DCHECK(a_reference_delta != 0);
157 MOJO_DCHECK(b_denominator != 0); 158 MOJO_DCHECK(b_reference_delta != 0);
158 MOJO_DCHECK(product_numerator != nullptr); 159 MOJO_DCHECK(product_subject_delta != nullptr);
159 MOJO_DCHECK(product_denominator != nullptr); 160 MOJO_DCHECK(product_reference_delta != nullptr);
160 161
161 uint64_t numerator = static_cast<uint64_t>(a_numerator) * b_numerator; 162 uint64_t subject_delta =
162 uint64_t denominator = static_cast<uint64_t>(a_denominator) * b_denominator; 163 static_cast<uint64_t>(a_subject_delta) * b_subject_delta;
164 uint64_t reference_delta =
165 static_cast<uint64_t>(a_reference_delta) * b_reference_delta;
163 166
164 ReduceRatio(&numerator, &denominator); 167 ReduceRatio(&subject_delta, &reference_delta);
165 168
166 if (numerator > std::numeric_limits<uint32_t>::max() || 169 if (subject_delta > std::numeric_limits<uint32_t>::max() ||
167 denominator > std::numeric_limits<uint32_t>::max()) { 170 reference_delta > std::numeric_limits<uint32_t>::max()) {
168 MOJO_DCHECK(!exact); 171 MOJO_DCHECK(!exact);
169 172
170 do { 173 do {
171 numerator >>= 1; 174 subject_delta >>= 1;
172 denominator >>= 1; 175 reference_delta >>= 1;
173 } while (numerator > std::numeric_limits<uint32_t>::max() || 176 } while (subject_delta > std::numeric_limits<uint32_t>::max() ||
174 denominator > std::numeric_limits<uint32_t>::max()); 177 reference_delta > std::numeric_limits<uint32_t>::max());
175 178
176 if (denominator == 0) { 179 if (reference_delta == 0) {
177 // Product is larger than we can represent. Return the largest value we 180 // Product is larger than we can represent. Return the largest value we
178 // can represent. 181 // can represent.
179 *product_numerator = std::numeric_limits<uint32_t>::max(); 182 *product_subject_delta = std::numeric_limits<uint32_t>::max();
180 *product_denominator = 1; 183 *product_reference_delta = 1;
181 return; 184 return;
182 } 185 }
183 } 186 }
184 187
185 *product_numerator = static_cast<uint32_t>(numerator); 188 *product_subject_delta = static_cast<uint32_t>(subject_delta);
186 *product_denominator = static_cast<uint32_t>(denominator); 189 *product_reference_delta = static_cast<uint32_t>(reference_delta);
187 } 190 }
188 191
189 // static 192 // static
190 int64_t Ratio::Scale(int64_t value, uint32_t numerator, uint32_t denominator) { 193 int64_t TimelineRate::Scale(int64_t value,
194 uint32_t subject_delta,
195 uint32_t reference_delta) {
191 static constexpr uint64_t abs_of_min_int64 = 196 static constexpr uint64_t abs_of_min_int64 =
192 static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1; 197 static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1;
193 198
194 MOJO_DCHECK(denominator != 0u); 199 MOJO_DCHECK(reference_delta != 0u);
195 200
196 bool overflow; 201 bool overflow;
197 202
198 uint64_t abs_result; 203 uint64_t abs_result;
199 204
200 if (value >= 0) { 205 if (value >= 0) {
201 abs_result = ScaleUInt64(static_cast<uint64_t>(value), numerator, 206 abs_result = ScaleUInt64(static_cast<uint64_t>(value), subject_delta,
202 denominator, false, &overflow); 207 reference_delta, false, &overflow);
203 } else if (value == std::numeric_limits<int64_t>::min()) { 208 } else if (value == std::numeric_limits<int64_t>::min()) {
204 abs_result = ScaleUInt64(abs_of_min_int64, numerator, denominator, 209 abs_result = ScaleUInt64(abs_of_min_int64, subject_delta, reference_delta,
205 true, &overflow); 210 true, &overflow);
206 } else { 211 } else {
207 abs_result = ScaleUInt64(static_cast<uint64_t>(-value), numerator, 212 abs_result = ScaleUInt64(static_cast<uint64_t>(-value), subject_delta,
208 denominator, true, &overflow); 213 reference_delta, true, &overflow);
209 } 214 }
210 215
211 if (overflow) { 216 if (overflow) {
212 return Ratio::kOverflow; 217 return TimelineRate::kOverflow;
213 } 218 }
214 219
215 // Make sure we won't overflow when we cast to int64_t. 220 // Make sure we won't overflow when we cast to int64_t.
216 if (abs_result > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { 221 if (abs_result > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
217 if (value < 0 && abs_result == abs_of_min_int64) { 222 if (value < 0 && abs_result == abs_of_min_int64) {
218 return std::numeric_limits<int64_t>::min(); 223 return std::numeric_limits<int64_t>::min();
219 } 224 }
220 return Ratio::kOverflow; 225 return TimelineRate::kOverflow;
221 } 226 }
222 227
223 return value >= 0 ? static_cast<int64_t>(abs_result) 228 return value >= 0 ? static_cast<int64_t>(abs_result)
224 : -static_cast<int64_t>(abs_result); 229 : -static_cast<int64_t>(abs_result);
225 } 230 }
226 231
227 } // namespace media 232 } // namespace media
228 } // namespace mojo 233 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/media/common/cpp/timeline_rate.h ('k') | mojo/services/media/common/interfaces/timelines.mojom » ('j') | no next file with comments »

Powered by Google App Engine