2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "MediaTime.h"
33 #include <wtf/CheckedArithmetic.h>
34 #include <wtf/MathExtras.h>
40 static int32_t greatestCommonDivisor(int32_t a, int32_t b)
52 static int32_t leastCommonMultiple(int32_t a, int32_t b, int32_t &result)
54 return safeMultiply(a, b / greatestCommonDivisor(a, b), result);
57 static int32_t signum(int64_t val)
59 return (0 < val) - (val < 0);
62 const int32_t MediaTime::MaximumTimeScale = 0x7fffffffL;
64 MediaTime::MediaTime()
66 , m_timeScale(DefaultTimeScale)
71 MediaTime::MediaTime(int64_t value, int32_t scale, uint32_t flags)
78 MediaTime::~MediaTime()
82 MediaTime::MediaTime(const MediaTime& rhs)
87 MediaTime MediaTime::createWithFloat(float floatTime, int32_t timeScale)
89 if (floatTime != floatTime)
91 if (std::isinf(floatTime))
92 return std::signbit(floatTime) ? negativeInfiniteTime() : positiveInfiniteTime();
93 if (floatTime > numeric_limits<int64_t>::max())
94 return positiveInfiniteTime();
95 if (floatTime < numeric_limits<int64_t>::min())
96 return negativeInfiniteTime();
98 while (floatTime * timeScale > numeric_limits<int64_t>::max())
100 return MediaTime(static_cast<int64_t>(floatTime * timeScale), timeScale, Valid);
103 MediaTime MediaTime::createWithDouble(double doubleTime, int32_t timeScale)
105 if (doubleTime != doubleTime)
106 return invalidTime();
107 if (std::isinf(doubleTime))
108 return std::signbit(doubleTime) ? negativeInfiniteTime() : positiveInfiniteTime();
109 if (doubleTime > numeric_limits<int64_t>::max())
110 return positiveInfiniteTime();
111 if (doubleTime < numeric_limits<int64_t>::min())
112 return negativeInfiniteTime();
114 while (doubleTime * timeScale > numeric_limits<int64_t>::max())
116 return MediaTime(static_cast<int64_t>(doubleTime * timeScale), timeScale, Valid);
119 float MediaTime::toFloat() const
121 if (isInvalid() || isIndefinite())
122 return std::numeric_limits<float>::quiet_NaN();
123 if (isPositiveInfinite())
124 return std::numeric_limits<float>::infinity();
125 if (isNegativeInfinite())
126 return -std::numeric_limits<float>::infinity();
127 return static_cast<float>(m_timeValue) / m_timeScale;
130 double MediaTime::toDouble() const
132 if (isInvalid() || isIndefinite())
133 return std::numeric_limits<double>::quiet_NaN();
134 if (isPositiveInfinite())
135 return std::numeric_limits<double>::infinity();
136 if (isNegativeInfinite())
137 return -std::numeric_limits<double>::infinity();
138 return static_cast<double>(m_timeValue) / m_timeScale;
141 MediaTime& MediaTime::operator=(const MediaTime& rhs)
143 m_timeValue = rhs.m_timeValue;
144 m_timeScale = rhs.m_timeScale;
145 m_timeFlags = rhs.m_timeFlags;
149 MediaTime MediaTime::operator+(const MediaTime& rhs) const
151 if (rhs.isInvalid() || isInvalid())
152 return invalidTime();
154 if (rhs.isIndefinite() || isIndefinite())
155 return indefiniteTime();
157 if (isPositiveInfinite()) {
158 if (rhs.isNegativeInfinite())
159 return invalidTime();
160 return positiveInfiniteTime();
163 if (isNegativeInfinite()) {
164 if (rhs.isPositiveInfinite())
165 return invalidTime();
166 return negativeInfiniteTime();
169 int32_t commonTimeScale;
170 if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
171 commonTimeScale = MaximumTimeScale;
174 a.setTimeScale(commonTimeScale);
175 b.setTimeScale(commonTimeScale);
176 while (!safeAdd(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
177 if (commonTimeScale == 1)
178 return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
179 commonTimeScale /= 2;
180 a.setTimeScale(commonTimeScale);
181 b.setTimeScale(commonTimeScale);
186 MediaTime MediaTime::operator-(const MediaTime& rhs) const
188 if (rhs.isInvalid() || isInvalid())
189 return invalidTime();
191 if (rhs.isIndefinite() || isIndefinite())
192 return indefiniteTime();
194 if (isPositiveInfinite()) {
195 if (rhs.isPositiveInfinite())
196 return invalidTime();
197 return positiveInfiniteTime();
200 if (isNegativeInfinite()) {
201 if (rhs.isNegativeInfinite())
202 return invalidTime();
203 return negativeInfiniteTime();
206 int32_t commonTimeScale;
207 if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
208 commonTimeScale = MaximumTimeScale;
211 a.setTimeScale(commonTimeScale);
212 b.setTimeScale(commonTimeScale);
213 while (!safeSub(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
214 if (commonTimeScale == 1)
215 return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
216 commonTimeScale /= 2;
217 a.setTimeScale(commonTimeScale);
218 b.setTimeScale(commonTimeScale);
223 MediaTime MediaTime::operator*(int32_t rhs) const
226 return invalidTime();
229 return indefiniteTime();
234 if (isPositiveInfinite()) {
236 return positiveInfiniteTime();
237 return negativeInfiniteTime();
240 if (isNegativeInfinite()) {
242 return negativeInfiniteTime();
243 return positiveInfiniteTime();
248 while (!safeMultiply(a.m_timeValue, rhs, a.m_timeValue)) {
249 if (a.m_timeScale == 1)
250 return signum(a.m_timeValue) == signum(rhs) ? positiveInfiniteTime() : negativeInfiniteTime();
251 a.setTimeScale(a.m_timeScale / 2);
257 bool MediaTime::operator<(const MediaTime& rhs) const
259 return compare(rhs) == LessThan;
262 bool MediaTime::operator>(const MediaTime& rhs) const
264 return compare(rhs) == GreaterThan;
267 bool MediaTime::operator!=(const MediaTime& rhs) const
269 return compare(rhs) != EqualTo;
272 bool MediaTime::operator==(const MediaTime& rhs) const
274 return compare(rhs) == EqualTo;
277 bool MediaTime::operator>=(const MediaTime& rhs) const
279 return compare(rhs) >= EqualTo;
282 bool MediaTime::operator<=(const MediaTime& rhs) const
284 return compare(rhs) <= EqualTo;
287 MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs) const
289 if ((isPositiveInfinite() && rhs.isPositiveInfinite())
290 || (isNegativeInfinite() && rhs.isNegativeInfinite())
291 || (isInvalid() && rhs.isInvalid())
292 || (isIndefinite() && rhs.isIndefinite()))
301 if (rhs.isNegativeInfinite() || isPositiveInfinite())
304 if (rhs.isPositiveInfinite() || isNegativeInfinite())
310 if (rhs.isIndefinite())
313 int64_t rhsWhole = rhs.m_timeValue / rhs.m_timeScale;
314 int64_t lhsWhole = m_timeValue / m_timeScale;
315 if (lhsWhole > rhsWhole)
317 if (lhsWhole < rhsWhole)
320 int64_t rhsRemain = rhs.m_timeValue % rhs.m_timeScale;
321 int64_t lhsRemain = m_timeValue % m_timeScale;
322 int64_t lhsFactor = lhsRemain * rhs.m_timeScale;
323 int64_t rhsFactor = rhsRemain * m_timeScale;
325 if (lhsFactor == rhsFactor)
327 return lhsFactor > rhsFactor ? GreaterThan : LessThan;
330 const MediaTime& MediaTime::zeroTime()
332 static const MediaTime* time = new MediaTime(0, 1, Valid);
336 const MediaTime& MediaTime::invalidTime()
338 static const MediaTime* time = new MediaTime(-1, 1, 0);
342 const MediaTime& MediaTime::positiveInfiniteTime()
344 static const MediaTime* time = new MediaTime(0, 1, PositiveInfinite | Valid);
348 const MediaTime& MediaTime::negativeInfiniteTime()
350 static const MediaTime* time = new MediaTime(-1, 1, NegativeInfinite | Valid);
354 const MediaTime& MediaTime::indefiniteTime()
356 static const MediaTime* time = new MediaTime(0, 1, Indefinite | Valid);
360 void MediaTime::setTimeScale(int32_t timeScale)
362 if (timeScale == m_timeScale)
364 timeScale = std::min(MaximumTimeScale, timeScale);
365 int64_t wholePart = m_timeValue / m_timeScale;
367 // If setting the time scale will cause an overflow, divide the
368 // timescale by two until the number will fit, and round the
370 int64_t newWholePart;
371 while (!safeMultiply(wholePart, timeScale, newWholePart))
374 int64_t remainder = m_timeValue % m_timeScale;
375 m_timeValue = newWholePart + (remainder * timeScale) / m_timeScale;
376 m_timeScale = timeScale;
379 MediaTime abs(const MediaTime& rhs)
382 return MediaTime::invalidTime();
383 if (rhs.isNegativeInfinite() || rhs.isPositiveInfinite())
384 return MediaTime::positiveInfiniteTime();
386 val.m_timeValue *= signum(rhs.m_timeScale) * signum(rhs.m_timeValue);