| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2012 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * | |
| 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. | |
| 16 * | |
| 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. | |
| 27 */ | |
| 28 | |
| 29 #include "config.h" | |
| 30 #include "MediaTime.h" | |
| 31 | |
| 32 #include <algorithm> | |
| 33 #include <wtf/CheckedArithmetic.h> | |
| 34 #include <wtf/MathExtras.h> | |
| 35 | |
| 36 using namespace std; | |
| 37 | |
| 38 namespace WTF { | |
| 39 | |
| 40 static int32_t greatestCommonDivisor(int32_t a, int32_t b) | |
| 41 { | |
| 42 // Euclid's Algorithm | |
| 43 int32_t temp = 0; | |
| 44 while (b) { | |
| 45 temp = b; | |
| 46 b = a % b; | |
| 47 a = temp; | |
| 48 } | |
| 49 return a; | |
| 50 } | |
| 51 | |
| 52 static int32_t leastCommonMultiple(int32_t a, int32_t b, int32_t &result) | |
| 53 { | |
| 54 return safeMultiply(a, b / greatestCommonDivisor(a, b), result); | |
| 55 } | |
| 56 | |
| 57 const int32_t MediaTime::MaximumTimeScale = 0x7fffffffL; | |
| 58 | |
| 59 MediaTime::MediaTime() | |
| 60 : m_timeValue(0) | |
| 61 , m_timeScale(DefaultTimeScale) | |
| 62 , m_timeFlags(Valid) | |
| 63 { | |
| 64 } | |
| 65 | |
| 66 MediaTime::MediaTime(int64_t value, int32_t scale, uint32_t flags) | |
| 67 : m_timeValue(value) | |
| 68 , m_timeScale(scale) | |
| 69 , m_timeFlags(flags) | |
| 70 { | |
| 71 } | |
| 72 | |
| 73 MediaTime::~MediaTime() | |
| 74 { | |
| 75 } | |
| 76 | |
| 77 MediaTime::MediaTime(const MediaTime& rhs) | |
| 78 { | |
| 79 *this = rhs; | |
| 80 } | |
| 81 | |
| 82 MediaTime MediaTime::createWithFloat(float floatTime, int32_t timeScale) | |
| 83 { | |
| 84 if (floatTime != floatTime) | |
| 85 return invalidTime(); | |
| 86 if (std::isinf(floatTime)) | |
| 87 return std::signbit(floatTime) ? negativeInfiniteTime() : positiveInfini
teTime(); | |
| 88 if (floatTime > numeric_limits<int64_t>::max()) | |
| 89 return positiveInfiniteTime(); | |
| 90 if (floatTime < numeric_limits<int64_t>::min()) | |
| 91 return negativeInfiniteTime(); | |
| 92 | |
| 93 while (floatTime * timeScale > numeric_limits<int64_t>::max()) | |
| 94 timeScale /= 2; | |
| 95 return MediaTime(static_cast<int64_t>(floatTime * timeScale), timeScale, Val
id); | |
| 96 } | |
| 97 | |
| 98 MediaTime MediaTime::createWithDouble(double doubleTime, int32_t timeScale) | |
| 99 { | |
| 100 if (doubleTime != doubleTime) | |
| 101 return invalidTime(); | |
| 102 if (std::isinf(doubleTime)) | |
| 103 return std::signbit(doubleTime) ? negativeInfiniteTime() : positiveInfin
iteTime(); | |
| 104 if (doubleTime > numeric_limits<int64_t>::max()) | |
| 105 return positiveInfiniteTime(); | |
| 106 if (doubleTime < numeric_limits<int64_t>::min()) | |
| 107 return negativeInfiniteTime(); | |
| 108 | |
| 109 while (doubleTime * timeScale > numeric_limits<int64_t>::max()) | |
| 110 timeScale /= 2; | |
| 111 return MediaTime(static_cast<int64_t>(doubleTime * timeScale), timeScale, Va
lid); | |
| 112 } | |
| 113 | |
| 114 float MediaTime::toFloat() const | |
| 115 { | |
| 116 if (isInvalid() || isIndefinite()) | |
| 117 return std::numeric_limits<float>::quiet_NaN(); | |
| 118 if (isPositiveInfinite()) | |
| 119 return std::numeric_limits<float>::infinity(); | |
| 120 if (isNegativeInfinite()) | |
| 121 return -std::numeric_limits<float>::infinity(); | |
| 122 return static_cast<float>(m_timeValue) / m_timeScale; | |
| 123 } | |
| 124 | |
| 125 double MediaTime::toDouble() const | |
| 126 { | |
| 127 if (isInvalid() || isIndefinite()) | |
| 128 return std::numeric_limits<double>::quiet_NaN(); | |
| 129 if (isPositiveInfinite()) | |
| 130 return std::numeric_limits<double>::infinity(); | |
| 131 if (isNegativeInfinite()) | |
| 132 return -std::numeric_limits<double>::infinity(); | |
| 133 return static_cast<double>(m_timeValue) / m_timeScale; | |
| 134 } | |
| 135 | |
| 136 MediaTime& MediaTime::operator=(const MediaTime& rhs) | |
| 137 { | |
| 138 m_timeValue = rhs.m_timeValue; | |
| 139 m_timeScale = rhs.m_timeScale; | |
| 140 m_timeFlags = rhs.m_timeFlags; | |
| 141 return *this; | |
| 142 } | |
| 143 | |
| 144 MediaTime MediaTime::operator+(const MediaTime& rhs) const | |
| 145 { | |
| 146 if (rhs.isInvalid() || isInvalid()) | |
| 147 return invalidTime(); | |
| 148 | |
| 149 if (rhs.isIndefinite() || isIndefinite()) | |
| 150 return indefiniteTime(); | |
| 151 | |
| 152 if (isPositiveInfinite()) { | |
| 153 if (rhs.isNegativeInfinite()) | |
| 154 return invalidTime(); | |
| 155 return positiveInfiniteTime(); | |
| 156 } | |
| 157 | |
| 158 if (isNegativeInfinite()) { | |
| 159 if (rhs.isPositiveInfinite()) | |
| 160 return invalidTime(); | |
| 161 return negativeInfiniteTime(); | |
| 162 } | |
| 163 | |
| 164 int32_t commonTimeScale; | |
| 165 if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale
) || commonTimeScale > MaximumTimeScale) | |
| 166 commonTimeScale = MaximumTimeScale; | |
| 167 MediaTime a = *this; | |
| 168 MediaTime b = rhs; | |
| 169 a.setTimeScale(commonTimeScale); | |
| 170 b.setTimeScale(commonTimeScale); | |
| 171 while (!safeAdd(a.m_timeValue, b.m_timeValue, a.m_timeValue)) { | |
| 172 if (commonTimeScale == 1) | |
| 173 return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfinite
Time(); | |
| 174 commonTimeScale /= 2; | |
| 175 a.setTimeScale(commonTimeScale); | |
| 176 b.setTimeScale(commonTimeScale); | |
| 177 } | |
| 178 return a; | |
| 179 } | |
| 180 | |
| 181 MediaTime MediaTime::operator-(const MediaTime& rhs) const | |
| 182 { | |
| 183 if (rhs.isInvalid() || isInvalid()) | |
| 184 return invalidTime(); | |
| 185 | |
| 186 if (rhs.isIndefinite() || isIndefinite()) | |
| 187 return indefiniteTime(); | |
| 188 | |
| 189 if (isPositiveInfinite()) { | |
| 190 if (rhs.isPositiveInfinite()) | |
| 191 return invalidTime(); | |
| 192 return positiveInfiniteTime(); | |
| 193 } | |
| 194 | |
| 195 if (isNegativeInfinite()) { | |
| 196 if (rhs.isNegativeInfinite()) | |
| 197 return invalidTime(); | |
| 198 return negativeInfiniteTime(); | |
| 199 } | |
| 200 | |
| 201 int32_t commonTimeScale; | |
| 202 if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale
) || commonTimeScale > MaximumTimeScale) | |
| 203 commonTimeScale = MaximumTimeScale; | |
| 204 MediaTime a = *this; | |
| 205 MediaTime b = rhs; | |
| 206 a.setTimeScale(commonTimeScale); | |
| 207 b.setTimeScale(commonTimeScale); | |
| 208 while (!safeSub(a.m_timeValue, b.m_timeValue, a.m_timeValue)) { | |
| 209 if (commonTimeScale == 1) | |
| 210 return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfinite
Time(); | |
| 211 commonTimeScale /= 2; | |
| 212 a.setTimeScale(commonTimeScale); | |
| 213 b.setTimeScale(commonTimeScale); | |
| 214 } | |
| 215 return a; | |
| 216 } | |
| 217 | |
| 218 bool MediaTime::operator<(const MediaTime& rhs) const | |
| 219 { | |
| 220 return compare(rhs) == LessThan; | |
| 221 } | |
| 222 | |
| 223 bool MediaTime::operator>(const MediaTime& rhs) const | |
| 224 { | |
| 225 return compare(rhs) == GreaterThan; | |
| 226 } | |
| 227 | |
| 228 bool MediaTime::operator==(const MediaTime& rhs) const | |
| 229 { | |
| 230 return compare(rhs) == EqualTo; | |
| 231 } | |
| 232 | |
| 233 bool MediaTime::operator>=(const MediaTime& rhs) const | |
| 234 { | |
| 235 return compare(rhs) >= EqualTo; | |
| 236 } | |
| 237 | |
| 238 bool MediaTime::operator<=(const MediaTime& rhs) const | |
| 239 { | |
| 240 return compare(rhs) <= EqualTo; | |
| 241 } | |
| 242 | |
| 243 MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs) const | |
| 244 { | |
| 245 if ((isPositiveInfinite() && rhs.isPositiveInfinite()) | |
| 246 || (isNegativeInfinite() && rhs.isNegativeInfinite()) | |
| 247 || (isInvalid() && rhs.isInvalid()) | |
| 248 || (isIndefinite() && rhs.isIndefinite())) | |
| 249 return EqualTo; | |
| 250 | |
| 251 if (isInvalid()) | |
| 252 return GreaterThan; | |
| 253 | |
| 254 if (rhs.isInvalid()) | |
| 255 return LessThan; | |
| 256 | |
| 257 if (rhs.isNegativeInfinite() || isPositiveInfinite()) | |
| 258 return GreaterThan; | |
| 259 | |
| 260 if (rhs.isPositiveInfinite() || isNegativeInfinite()) | |
| 261 return LessThan; | |
| 262 | |
| 263 if (isIndefinite()) | |
| 264 return GreaterThan; | |
| 265 | |
| 266 if (rhs.isIndefinite()) | |
| 267 return LessThan; | |
| 268 | |
| 269 int64_t rhsWhole = rhs.m_timeValue / rhs.m_timeScale; | |
| 270 int64_t lhsWhole = m_timeValue / m_timeScale; | |
| 271 if (lhsWhole > rhsWhole) | |
| 272 return GreaterThan; | |
| 273 if (lhsWhole < rhsWhole) | |
| 274 return LessThan; | |
| 275 | |
| 276 int64_t rhsRemain = rhs.m_timeValue % rhs.m_timeScale; | |
| 277 int64_t lhsRemain = m_timeValue % m_timeScale; | |
| 278 int64_t lhsFactor = lhsRemain * rhs.m_timeScale; | |
| 279 int64_t rhsFactor = rhsRemain * m_timeScale; | |
| 280 | |
| 281 if (lhsFactor == rhsFactor) | |
| 282 return EqualTo; | |
| 283 return lhsFactor > rhsFactor ? GreaterThan : LessThan; | |
| 284 } | |
| 285 | |
| 286 const MediaTime& MediaTime::zeroTime() | |
| 287 { | |
| 288 static const MediaTime* time = new MediaTime(0, 1, Valid); | |
| 289 return *time; | |
| 290 } | |
| 291 | |
| 292 const MediaTime& MediaTime::invalidTime() | |
| 293 { | |
| 294 static const MediaTime* time = new MediaTime(-1, 1, 0); | |
| 295 return *time; | |
| 296 } | |
| 297 | |
| 298 const MediaTime& MediaTime::positiveInfiniteTime() | |
| 299 { | |
| 300 static const MediaTime* time = new MediaTime(0, 1, PositiveInfinite | Valid)
; | |
| 301 return *time; | |
| 302 } | |
| 303 | |
| 304 const MediaTime& MediaTime::negativeInfiniteTime() | |
| 305 { | |
| 306 static const MediaTime* time = new MediaTime(-1, 1, NegativeInfinite | Valid
); | |
| 307 return *time; | |
| 308 } | |
| 309 | |
| 310 const MediaTime& MediaTime::indefiniteTime() | |
| 311 { | |
| 312 static const MediaTime* time = new MediaTime(0, 1, Indefinite | Valid); | |
| 313 return *time; | |
| 314 } | |
| 315 | |
| 316 void MediaTime::setTimeScale(int32_t timeScale) | |
| 317 { | |
| 318 if (timeScale == m_timeScale) | |
| 319 return; | |
| 320 timeScale = std::min(MaximumTimeScale, timeScale); | |
| 321 int64_t wholePart = m_timeValue / m_timeScale; | |
| 322 | |
| 323 // If setting the time scale will cause an overflow, divide the | |
| 324 // timescale by two until the number will fit, and round the | |
| 325 // result. | |
| 326 int64_t newWholePart; | |
| 327 while (!safeMultiply(wholePart, timeScale, newWholePart)) | |
| 328 timeScale /= 2; | |
| 329 | |
| 330 int64_t remainder = m_timeValue % m_timeScale; | |
| 331 m_timeValue = newWholePart + (remainder * timeScale) / m_timeScale; | |
| 332 m_timeScale = timeScale; | |
| 333 } | |
| 334 | |
| 335 static int32_t signum(int64_t val) | |
| 336 { | |
| 337 return (0 < val) - (val < 0); | |
| 338 } | |
| 339 | |
| 340 MediaTime abs(const MediaTime& rhs) | |
| 341 { | |
| 342 if (rhs.isInvalid()) | |
| 343 return MediaTime::invalidTime(); | |
| 344 if (rhs.isNegativeInfinite() || rhs.isPositiveInfinite()) | |
| 345 return MediaTime::positiveInfiniteTime(); | |
| 346 MediaTime val = rhs; | |
| 347 val.m_timeValue *= signum(rhs.m_timeScale) * signum(rhs.m_timeValue); | |
| 348 return val; | |
| 349 } | |
| 350 | |
| 351 } | |
| 352 | |
| OLD | NEW |