Support a rational time class for use by media elements.
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jul 2012 16:31:07 +0000 (16:31 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jul 2012 16:31:07 +0000 (16:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88787

Source/JavaScriptCore:

Re-export WTF::MediaTime from JavaScriptCore.

Reviewed by Eric Carlson.

* JavaScriptCore.order:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:

Source/WTF:

Reviewed by Eric Carlson.

Add a new MediaTime class which implements rational math operations.

Add common constructors and assignment operators:
* wtf/MediaTime.cpp: Added.
(WTF::MediaTime::MediaTime):
(WTF::MediaTime::~MediaTime):
(WTF::MediaTime::operator=):

Add common math operators:
* wtf/MediaTime.cpp:
(WTF::MediaTime::operator+):
(WTF::MediaTime::operator-):
(WTF::MediaTime::operator<):
(WTF::MediaTime::operator>):
(WTF::MediaTime::operator==):
(WTF::MediaTime::operator>=):
(WTF::MediaTime::operator<=):

Add functions to check the MeiaTime time type flags:
* wtf/MediaTime.h:
(WTF::MediaTime::isValid):
(WTF::MediaTime::isInvalid):
(WTF::MediaTime::hasBeenRounde):
(WTF::MediaTime::isPositiveInfinite):
(WTF::MediaTime::isNegativeInfinite):
(WTF::MediaTime::isIndefinite):

Add constants for commonly used MediaTime values:
(WTF::MediaTime::zeroTime):
(WTF::MediaTime::invalidTime):
(WTF::MediaTime::positiveInfiniteTime):
(WTF::MediaTime::negativeInfiniteTime):
(WTF::MediaTime::indefiniteTime):

Add explicit conversion functions to convert to and from floating point values.
* wtf/MediaTime.cpp:
(WTF::MediaTime::createWithFloat):
(WTF::MediaTime::createWithDouble):
(WTF::MediaTime::toFloat):
(WTF::MediaTime::toDouble):

Add some useful exported functions:
* wtf/MediaTime.cpp:
(WTF::MediaTime::compare): Master function for the comparison operators above.
(WTF::MediaTime::setTimeScale): Rescale the time value to a new time scale.
(WTF::abs): Return an absolute value for the current MediaTime.

Static utility functions to implement the above:
* wtf/MediaTime.cpp:
(WTF::greatestCommonDivisor):
(WTF::leastCommonMultiple):
(WTF::signum):

Windows-only implementations of isinf and signbit:
* wtf/MediaTime.cpp:
(std::isinf):
(std::signbit):

Add the new class to platform build files:
* GNUmakefile.list.am:
* WTF.gypi:
* WTF.pro:
* WTF.vcproj/WTF.vcproj:
* WTF.xcodeproj/project.pbxproj:

Tools:

Add unit tests for the WTF::MediaTime class.

Reviewed by Eric Carlson.

* TestWebKitAPI/GNUmakefile.am:
* TestWebKitAPI/TestWebKitAPI.gypi:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/MediaTime.cpp: Added.
* TestWebKitAPI/win/TestWebKitAPI.vcproj:
(WTF::operator<<):
(TestWebKitAPI):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@123878 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.order
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/WTF/ChangeLog
Source/WTF/GNUmakefile.list.am
Source/WTF/WTF.gypi
Source/WTF/WTF.pro
Source/WTF/WTF.vcproj/WTF.vcproj
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/MediaTime.cpp [new file with mode: 0644]
Source/WTF/wtf/MediaTime.h [new file with mode: 0644]
Tools/ChangeLog
Tools/TestWebKitAPI/GNUmakefile.am
Tools/TestWebKitAPI/TestWebKitAPI.gypi
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/win/TestWebKitAPI.vcproj

index d1d1fe13888a728dea09960347fa9d13484ed16f..992c928eef774ba25e5fcab3f44a1c224f6fe06d 100644 (file)
@@ -1,3 +1,15 @@
+2012-07-27  Jer Noble  <jer.noble@apple.com>
+
+        Support a rational time class for use by media elements.
+        https://bugs.webkit.org/show_bug.cgi?id=88787
+
+        Re-export WTF::MediaTime from JavaScriptCore.
+
+        Reviewed by Eric Carlson.
+
+        * JavaScriptCore.order:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+
 2012-07-26  Filip Pizlo  <fpizlo@apple.com>
 
         JSObject::reallocateStorageIfNecessary is neither used nor defined
index 3a450075a1343e59e7b1eda11a5f7cd803c865aa..0742a0a0e2b6dcdd84bef78cbc16e7eab899a52b 100644 (file)
@@ -2494,3 +2494,16 @@ __ZN3WTF6VectorIN3JSC10ASTBuilder14AssignmentInfoELm10EE14expandCapacityEm
 _cti_op_put_by_id_direct_generic
 __ZN3WTF9HashTableIPN3JSC16FunctionBodyNodeESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E4findIS3_NS_22IdentityHashTranslatorIS3_S5_S9_EEEENS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EERKT_
 __ZN3WTF9HashTableIPN3JSC16FunctionBodyNodeESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6expandEv
+__ZN3WTF3absERKNS_9MediaTimeE
+__ZN3WTF9MediaTime11invalidTimeEv
+__ZN3WTF9MediaTime14indefiniteTimeEv
+__ZN3WTF9MediaTime15createWithFloatEfi
+__ZN3WTF9MediaTime16createWithDoubleEdi
+__ZN3WTF9MediaTime20negativeInfiniteTimeEv
+__ZN3WTF9MediaTime20positiveInfiniteTimeEv
+__ZN3WTF9MediaTimeD1Ev
+__ZNK3WTF9MediaTimegtERKS0_
+__ZNK3WTF9MediaTimeltERKS0_
+__ZNK3WTF9MediaTimemiERKS0_
+__ZNK3WTF9MediaTimeplERKS0_
+
index 2e868588423771ad19b13ac6cd2cc95f7b15925f..5f27859d8a4dc84d54337162ce0ddce6d83d2ac1 100755 (executable)
@@ -379,6 +379,23 @@ EXPORTS
     ?writable@PropertyDescriptor@JSC@@QBE_NXZ
     ?writeBarrier@HandleSet@JSC@@QAEXPAVJSValue@2@ABV32@@Z
     ?yield@WTF@@YAXXZ
+    ?toDouble@MediaTime@WTF@@QBENXZ 
+    ?toFloat@MediaTime@WTF@@QBEMXZ 
+    ?createWithDouble@MediaTime@WTF@@SA?AV12@NH@Z 
+    ?createWithFloat@MediaTime@WTF@@SA?AV12@MH@Z 
+    ?abs@WTF@@YA?AVMediaTime@1@ABV21@@Z 
+    ?zeroTime@MediaTime@WTF@@SAABV12@XZ 
+    ??GMediaTime@WTF@@QBE?AV01@ABV01@@Z 
+    ??HMediaTime@WTF@@QBE?AV01@ABV01@@Z 
+    ??1MediaTime@WTF@@QAE@XZ 
+    ??0MediaTime@WTF@@QAE@_JHI@Z 
+    ?indefiniteTime@MediaTime@WTF@@SAABV12@XZ 
+    ?invalidTime@MediaTime@WTF@@SAABV12@XZ 
+    ??8MediaTime@WTF@@QBE_NABV01@@Z 
+    ??MMediaTime@WTF@@QBE_NABV01@@Z 
+    ??OMediaTime@WTF@@QBE_NABV01@@Z 
+    ?positiveInfiniteTime@MediaTime@WTF@@SAABV12@XZ 
+    ?negativeInfiniteTime@MediaTime@WTF@@SAABV12@XZ
     WTFGetBacktrace
     WTFInvokeCrashHook
     WTFLog
index 89dce3d46b531545d4cb32549d1b0e157f5861ed..599366d1679d508d4d53606bb2c9b1e5f03e0f06 100644 (file)
@@ -1,3 +1,75 @@
+2012-07-27  Jer Noble  <jer.noble@apple.com>
+
+        Support a rational time class for use by media elements.
+        https://bugs.webkit.org/show_bug.cgi?id=88787
+
+        Reviewed by Eric Carlson.
+
+        Add a new MediaTime class which implements rational math operations.
+
+        Add common constructors and assignment operators:
+        * wtf/MediaTime.cpp: Added.
+        (WTF::MediaTime::MediaTime):
+        (WTF::MediaTime::~MediaTime):
+        (WTF::MediaTime::operator=):
+
+        Add common math operators:
+        * wtf/MediaTime.cpp:
+        (WTF::MediaTime::operator+):
+        (WTF::MediaTime::operator-):
+        (WTF::MediaTime::operator<):
+        (WTF::MediaTime::operator>):
+        (WTF::MediaTime::operator==):
+        (WTF::MediaTime::operator>=):
+        (WTF::MediaTime::operator<=):
+
+        Add functions to check the MeiaTime time type flags:
+        * wtf/MediaTime.h:
+        (WTF::MediaTime::isValid):
+        (WTF::MediaTime::isInvalid):
+        (WTF::MediaTime::hasBeenRounde):
+        (WTF::MediaTime::isPositiveInfinite):
+        (WTF::MediaTime::isNegativeInfinite):
+        (WTF::MediaTime::isIndefinite):
+
+        Add constants for commonly used MediaTime values:
+        (WTF::MediaTime::zeroTime):
+        (WTF::MediaTime::invalidTime):
+        (WTF::MediaTime::positiveInfiniteTime):
+        (WTF::MediaTime::negativeInfiniteTime):
+        (WTF::MediaTime::indefiniteTime):
+
+        Add explicit conversion functions to convert to and from floating point values.
+        * wtf/MediaTime.cpp:
+        (WTF::MediaTime::createWithFloat):
+        (WTF::MediaTime::createWithDouble):
+        (WTF::MediaTime::toFloat):
+        (WTF::MediaTime::toDouble):
+
+        Add some useful exported functions:
+        * wtf/MediaTime.cpp:
+        (WTF::MediaTime::compare): Master function for the comparison operators above.
+        (WTF::MediaTime::setTimeScale): Rescale the time value to a new time scale.
+        (WTF::abs): Return an absolute value for the current MediaTime.
+
+        Static utility functions to implement the above:
+        * wtf/MediaTime.cpp:
+        (WTF::greatestCommonDivisor):
+        (WTF::leastCommonMultiple):
+        (WTF::signum):
+
+        Windows-only implementations of isinf and signbit:
+        * wtf/MediaTime.cpp:
+        (std::isinf):
+        (std::signbit):
+
+        Add the new class to platform build files:
+        * GNUmakefile.list.am:
+        * WTF.gypi:
+        * WTF.pro:
+        * WTF.vcproj/WTF.vcproj:
+        * WTF.xcodeproj/project.pbxproj:
+
 2012-07-27  Wei James  <james.wei@intel.com>
 
         set WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED for chromium android
index bb68bc26852b44649d99d8ec376d49e9bd344156..2b844af25494393e2cd9a5a862b0742543996876 100644 (file)
@@ -76,6 +76,8 @@ wtf_sources += \
     Source/WTF/wtf/MainThread.h \
     Source/WTF/wtf/MallocZoneSupport.h \
     Source/WTF/wtf/MathExtras.h \
+    Source/WTF/wtf/MediaTime.h \
+    Source/WTF/wtf/MediaTime.cpp \
     Source/WTF/wtf/MessageQueue.h \
     Source/WTF/wtf/MetaAllocator.cpp \
     Source/WTF/wtf/MetaAllocator.h \
index ebb41a45430cc4deb4a6a184c849357a5ecf37bf..59c74b311a6e2ce62df480cb6cb72545c5d8fc27 100644 (file)
             'wtf/MD5.cpp',
             'wtf/MainThread.cpp',
             'wtf/MallocZoneSupport.h',
+            'wtf/MediaTime.h',
+            'wtf/MediaTime.cpp',
             'wtf/NullPtr.cpp',
             'wtf/NumberOfCores.cpp',
             'wtf/NumberOfCores.h',
index 68d8471127c72bf2ae160513128b5baad0ecd3d9..72d1d712a8662c4a650b9dcb6e4bd207cc1b51bb 100644 (file)
@@ -80,6 +80,7 @@ HEADERS += \
     MallocZoneSupport.h \
     MathExtras.h \
     MD5.h \
+    MediaTime.h \
     MessageQueue.h \
     MetaAllocator.h \
     MetaAllocatorHandle.h \
@@ -194,6 +195,7 @@ SOURCES += \
     HashTable.cpp \
     MD5.cpp \
     MainThread.cpp \
+    MediaTime.cpp \
     MetaAllocator.cpp \
     NullPtr.cpp \
     NumberOfCores.cpp \
index 1ac32b4d6773b0a1c9684a0247cb5ae3634cf034..94e8326f39949de8f2eee43a61bb261b47e21ee5 100644 (file)
                        RelativePath="..\wtf\MD5.h"
                        >
                </File>
+               <File
+                       RelativePath="..\wtf\MediaTime.h"
+                       >
+               </File>
+               <File
+                       RelativePath="..\wtf\MediaTime.cpp"
+                       >
+               </File>
                <File
                        RelativePath="..\wtf\MessageQueue.h"
                        >
index 372c15ec0c71cc40d1cbcb9e80c454571d2485ec..f5347b24dccc2734ebf7dffc913fa3b9653939c3 100644 (file)
                A8A47486151A825B004123FF /* WTFThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A4737A151A825B004123FF /* WTFThreadData.cpp */; };
                A8A47487151A825B004123FF /* WTFThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4737B151A825B004123FF /* WTFThreadData.h */; };
                A8A4748C151A8264004123FF /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4748B151A8264004123FF /* config.h */; };
+               CD5497AC15857D0300B5BC30 /* MediaTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD5497AA15857D0300B5BC30 /* MediaTime.cpp */; };
+               CD5497AD15857D0300B5BC30 /* MediaTime.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5497AB15857D0300B5BC30 /* MediaTime.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
                A8A4737A151A825B004123FF /* WTFThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WTFThreadData.cpp; sourceTree = "<group>"; };
                A8A4737B151A825B004123FF /* WTFThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFThreadData.h; sourceTree = "<group>"; };
                A8A4748B151A8264004123FF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+               CD5497AA15857D0300B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaTime.cpp; sourceTree = "<group>"; };
+               CD5497AB15857D0300B5BC30 /* MediaTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaTime.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                A8A472C9151A825B004123FF /* MathExtras.h */,
                                A8A472CA151A825B004123FF /* MD5.cpp */,
                                A8A472CB151A825B004123FF /* MD5.h */,
+                               CD5497AA15857D0300B5BC30 /* MediaTime.cpp */,
+                               CD5497AB15857D0300B5BC30 /* MediaTime.h */,
                                A8A472CC151A825B004123FF /* MessageQueue.h */,
                                A8A472CD151A825B004123FF /* MetaAllocator.cpp */,
                                A8A472CE151A825B004123FF /* MetaAllocator.h */,
                                A8A473E7151A825B004123FF /* MallocZoneSupport.h in Headers */,
                                A8A473E8151A825B004123FF /* MathExtras.h in Headers */,
                                A8A473EA151A825B004123FF /* MD5.h in Headers */,
+                               CD5497AD15857D0300B5BC30 /* MediaTime.h in Headers */,
                                A8A473EB151A825B004123FF /* MessageQueue.h in Headers */,
                                A8A473ED151A825B004123FF /* MetaAllocator.h in Headers */,
                                A8A473EE151A825B004123FF /* MetaAllocatorHandle.h in Headers */,
                                A8A473D8151A825B004123FF /* HashTable.cpp in Sources */,
                                A8A473E5151A825B004123FF /* MainThread.cpp in Sources */,
                                A8A473E4151A825B004123FF /* MainThreadMac.mm in Sources */,
+                               CD5497AC15857D0300B5BC30 /* MediaTime.cpp in Sources */,
                                A8A473E9151A825B004123FF /* MD5.cpp in Sources */,
                                A8A473EC151A825B004123FF /* MetaAllocator.cpp in Sources */,
                                A8A473F2151A825B004123FF /* NullPtr.cpp in Sources */,
diff --git a/Source/WTF/wtf/MediaTime.cpp b/Source/WTF/wtf/MediaTime.cpp
new file mode 100644 (file)
index 0000000..ce58bc2
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MediaTime.h"
+
+#include <algorithm>
+#include <wtf/CheckedArithmetic.h>
+
+#if PLATFORM(WIN)
+// Work around Visual Studio 2008's lack of an isinf or signbit method in STL.
+namespace std {
+    static bool isinf(double number) { return !_finite(number) && !_isnan(number); }
+    static int signbit(double number) { return number < 0; }
+}
+#endif
+
+using namespace std;
+
+namespace WTF {
+
+static int32_t greatestCommonDivisor(int32_t a, int32_t b)
+{
+    // Euclid's Algorithm
+    int32_t temp = 0;
+    while (b) {
+        temp = b;
+        b = a % b;
+        a = temp;
+    }
+    return a;
+}
+
+static int32_t leastCommonMultiple(int32_t a, int32_t b, int32_t &result)
+{
+    return safeMultiply(a, b / greatestCommonDivisor(a, b), result);
+}
+
+const int32_t MediaTime::MaximumTimeScale = 0x7fffffffL;
+
+MediaTime::MediaTime()
+    : m_timeValue(0)
+    , m_timeScale(DefaultTimeScale)
+    , m_timeFlags(Valid)
+{
+}
+
+MediaTime::MediaTime(int64_t value, int32_t scale, uint32_t flags)
+    : m_timeValue(value)
+    , m_timeScale(scale)
+    , m_timeFlags(flags)
+{
+}
+
+MediaTime::~MediaTime()
+{
+}
+
+MediaTime::MediaTime(const MediaTime& rhs)
+{
+    *this = rhs;
+}
+
+MediaTime MediaTime::createWithFloat(float floatTime, int32_t timeScale)
+{
+    if (floatTime != floatTime)
+        return invalidTime();
+    if (std::isinf(floatTime))
+        return std::signbit(floatTime) ? negativeInfiniteTime() : positiveInfiniteTime();
+    if (floatTime > numeric_limits<int64_t>::max())
+        return positiveInfiniteTime();
+    if (floatTime < numeric_limits<int64_t>::min())
+        return negativeInfiniteTime();
+
+    while (floatTime * timeScale > numeric_limits<int64_t>::max())
+        timeScale /= 2;
+    return MediaTime(static_cast<int64_t>(floatTime * timeScale), timeScale, Valid);
+}
+
+MediaTime MediaTime::createWithDouble(double doubleTime, int32_t timeScale)
+{
+    if (doubleTime != doubleTime)
+        return invalidTime();
+    if (std::isinf(doubleTime))
+        return std::signbit(doubleTime) ? negativeInfiniteTime() : positiveInfiniteTime();
+    if (doubleTime > numeric_limits<int64_t>::max())
+        return positiveInfiniteTime();
+    if (doubleTime < numeric_limits<int64_t>::min())
+        return negativeInfiniteTime();
+
+    while (doubleTime * timeScale > numeric_limits<int64_t>::max())
+        timeScale /= 2;
+    return MediaTime(static_cast<int64_t>(doubleTime * timeScale), timeScale, Valid);
+}
+
+float MediaTime::toFloat() const
+{
+    if (isInvalid() || isIndefinite())
+        return std::numeric_limits<float>::quiet_NaN();
+    if (isPositiveInfinite())
+        return std::numeric_limits<float>::infinity();
+    if (isNegativeInfinite())
+        return -std::numeric_limits<float>::infinity();
+    return static_cast<float>(m_timeValue) / m_timeScale;
+}
+
+double MediaTime::toDouble() const
+{
+    if (isInvalid() || isIndefinite())
+        return std::numeric_limits<double>::quiet_NaN();
+    if (isPositiveInfinite())
+        return std::numeric_limits<double>::infinity();
+    if (isNegativeInfinite())
+        return -std::numeric_limits<double>::infinity();
+    return static_cast<double>(m_timeValue) / m_timeScale;
+}
+
+MediaTime& MediaTime::operator=(const MediaTime& rhs)
+{
+    m_timeValue = rhs.m_timeValue;
+    m_timeScale = rhs.m_timeScale;
+    m_timeFlags = rhs.m_timeFlags;
+    return *this;
+}
+
+MediaTime MediaTime::operator+(const MediaTime& rhs) const
+{
+    if (rhs.isInvalid() || isInvalid())
+        return invalidTime();
+
+    if (rhs.isIndefinite() || isIndefinite())
+        return indefiniteTime();
+
+    if (isPositiveInfinite()) {
+        if (rhs.isNegativeInfinite())
+            return invalidTime();
+        return positiveInfiniteTime();
+    }
+
+    if (isNegativeInfinite()) {
+        if (rhs.isPositiveInfinite())
+            return invalidTime();
+        return negativeInfiniteTime();
+    }
+
+    int32_t commonTimeScale;
+    if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
+        commonTimeScale = MaximumTimeScale;
+    MediaTime a = *this;
+    MediaTime b = rhs;
+    a.setTimeScale(commonTimeScale);
+    b.setTimeScale(commonTimeScale);
+    while (!safeAdd(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
+        if (commonTimeScale == 1)
+            return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
+        commonTimeScale /= 2;
+        a.setTimeScale(commonTimeScale);
+        b.setTimeScale(commonTimeScale);
+    }
+    return a;
+}
+
+MediaTime MediaTime::operator-(const MediaTime& rhs) const
+{
+    if (rhs.isInvalid() || isInvalid())
+        return invalidTime();
+
+    if (rhs.isIndefinite() || isIndefinite())
+        return indefiniteTime();
+
+    if (isPositiveInfinite()) {
+        if (rhs.isPositiveInfinite())
+            return invalidTime();
+        return positiveInfiniteTime();
+    }
+
+    if (isNegativeInfinite()) {
+        if (rhs.isNegativeInfinite())
+            return invalidTime();
+        return negativeInfiniteTime();
+    }
+
+    int32_t commonTimeScale;
+    if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
+        commonTimeScale = MaximumTimeScale;
+    MediaTime a = *this;
+    MediaTime b = rhs;
+    a.setTimeScale(commonTimeScale);
+    b.setTimeScale(commonTimeScale);
+    while (!safeSub(a.m_timeValue, b.m_timeValue, a.m_timeValue)) {
+        if (commonTimeScale == 1)
+            return a.m_timeValue > 0 ? positiveInfiniteTime() : negativeInfiniteTime();
+        commonTimeScale /= 2;
+        a.setTimeScale(commonTimeScale);
+        b.setTimeScale(commonTimeScale);
+    }
+    return a;
+}
+
+bool MediaTime::operator<(const MediaTime& rhs) const
+{
+    return compare(rhs) == LessThan;
+}
+
+bool MediaTime::operator>(const MediaTime& rhs) const
+{
+    return compare(rhs) == GreaterThan;
+}
+
+bool MediaTime::operator==(const MediaTime& rhs) const
+{
+    return compare(rhs) == EqualTo;
+}
+
+bool MediaTime::operator>=(const MediaTime& rhs) const
+{
+    return compare(rhs) >= EqualTo;
+}
+
+bool MediaTime::operator<=(const MediaTime& rhs) const
+{
+    return compare(rhs) <= EqualTo;
+}
+
+MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs) const
+{
+    if ((isPositiveInfinite() && rhs.isPositiveInfinite())
+        || (isNegativeInfinite() && rhs.isNegativeInfinite())
+        || (isInvalid() && rhs.isInvalid())
+        || (isIndefinite() && rhs.isIndefinite()))
+        return EqualTo;
+
+    if (isInvalid())
+        return GreaterThan;
+
+    if (rhs.isInvalid())
+        return LessThan;
+
+    if (rhs.isNegativeInfinite() || isPositiveInfinite())
+        return GreaterThan;
+
+    if (rhs.isPositiveInfinite() || isNegativeInfinite())
+        return LessThan;
+
+    if (isIndefinite())
+        return GreaterThan;
+
+    if (rhs.isIndefinite())
+        return LessThan;
+
+    int64_t rhsWhole = rhs.m_timeValue / rhs.m_timeScale;
+    int64_t lhsWhole = m_timeValue / m_timeScale;
+    if (lhsWhole > rhsWhole)
+        return GreaterThan;
+    if (lhsWhole < rhsWhole)
+        return LessThan;
+
+    int64_t rhsRemain = rhs.m_timeValue % rhs.m_timeScale;
+    int64_t lhsRemain = m_timeValue % m_timeScale;
+    int64_t lhsFactor = lhsRemain * rhs.m_timeScale;
+    int64_t rhsFactor = rhsRemain * m_timeScale;
+
+    if (lhsFactor == rhsFactor)
+        return EqualTo;
+    return lhsFactor > rhsFactor ? GreaterThan : LessThan;
+}
+
+const MediaTime& MediaTime::zeroTime()
+{
+    static const MediaTime* time = new MediaTime(0, 1, Valid);
+    return *time;
+}
+
+const MediaTime& MediaTime::invalidTime()
+{
+    static const MediaTime* time = new MediaTime(-1, 1, 0);
+    return *time;
+}
+
+const MediaTime& MediaTime::positiveInfiniteTime()
+{
+    static const MediaTime* time = new MediaTime(0, 1, PositiveInfinite | Valid);
+    return *time;
+}
+
+const MediaTime& MediaTime::negativeInfiniteTime()
+{
+    static const MediaTime* time = new MediaTime(-1, 1, NegativeInfinite | Valid);
+    return *time;
+}
+
+const MediaTime& MediaTime::indefiniteTime()
+{
+    static const MediaTime* time = new MediaTime(0, 1, Indefinite | Valid);
+    return *time;
+}
+
+void MediaTime::setTimeScale(int32_t timeScale)
+{
+    if (timeScale == m_timeScale)
+        return;
+    timeScale = std::min(MaximumTimeScale, timeScale);
+    int64_t wholePart = m_timeValue / m_timeScale;
+
+    // If setting the time scale will cause an overflow, divide the
+    // timescale by two until the number will fit, and round the
+    // result.
+    int64_t newWholePart;
+    while (!safeMultiply(wholePart, timeScale, newWholePart))
+        timeScale /= 2;
+
+    int64_t remainder = m_timeValue % m_timeScale;
+    m_timeValue = newWholePart + (remainder * timeScale) / m_timeScale;
+    m_timeScale = timeScale;
+}
+
+static int32_t signum(int64_t val)
+{
+    return (0 < val) - (val < 0);
+}
+
+MediaTime abs(const MediaTime& rhs)
+{
+    if (rhs.isInvalid())
+        return MediaTime::invalidTime();
+    if (rhs.isNegativeInfinite() || rhs.isPositiveInfinite())
+        return MediaTime::positiveInfiniteTime();
+    MediaTime val = rhs;
+    val.m_timeValue *= signum(rhs.m_timeScale) * signum(rhs.m_timeValue);
+    return val;
+}
+
+}
+
diff --git a/Source/WTF/wtf/MediaTime.h b/Source/WTF/wtf/MediaTime.h
new file mode 100644 (file)
index 0000000..430d3f5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cmath>
+#include <limits>
+#include <math.h>
+#include <stdint.h>
+
+namespace WTF {
+
+class WTF_EXPORT_PRIVATE MediaTime {
+public:
+    enum {
+        Valid = 1 << 0,
+        HasBeenRounded = 1 << 1,
+        PositiveInfinite = 1 << 2,
+        NegativeInfinite = 1 << 3,
+        Indefinite = 1 << 4,
+    };
+
+    MediaTime();
+    MediaTime(int64_t value, int32_t scale = DefaultTimeScale, uint32_t flags = Valid);
+    MediaTime(const MediaTime& rhs);
+    ~MediaTime();
+
+    static MediaTime createWithFloat(float floatTime, int32_t timeScale = DefaultTimeScale);
+    static MediaTime createWithDouble(double doubleTime, int32_t timeScale = DefaultTimeScale);
+
+    float toFloat() const;
+    double toDouble() const;
+
+    MediaTime& operator=(const MediaTime& rhs);
+    MediaTime operator+(const MediaTime& rhs) const;
+    MediaTime operator-(const MediaTime& rhs) const;
+    bool operator<(const MediaTime& rhs) const;
+    bool operator>(const MediaTime& rhs) const;
+    bool operator==(const MediaTime& rhs) const;
+    bool operator>=(const MediaTime& rhs) const;
+    bool operator<=(const MediaTime& rhs) const;
+
+    typedef enum {
+        LessThan = -1,
+        EqualTo = 0,
+        GreaterThan = 1,
+    } ComparisonFlags;
+
+    ComparisonFlags compare(const MediaTime& rhs) const;
+
+    bool isValid() const { return m_timeFlags & Valid; }
+    bool isInvalid() const { return !isValid(); }
+    bool hasBeenRounded() const { return m_timeFlags & HasBeenRounded; }
+    bool isPositiveInfinite() const { return m_timeFlags & PositiveInfinite; }
+    bool isNegativeInfinite() const { return m_timeFlags & NegativeInfinite; }
+    bool isIndefinite() const { return m_timeFlags & Indefinite; }
+
+    static const MediaTime& zeroTime();
+    static const MediaTime& invalidTime();
+    static const MediaTime& positiveInfiniteTime();
+    static const MediaTime& negativeInfiniteTime();
+    static const MediaTime& indefiniteTime();
+
+    const int64_t& timeValue() const { return m_timeValue; }
+    const int32_t& timeScale() const { return m_timeScale; }
+
+    friend MediaTime abs(const MediaTime& rhs);
+private:
+    static const int32_t DefaultTimeScale = 6000;
+    static const int32_t MaximumTimeScale;
+
+    void setTimeScale(int32_t);
+
+    int64_t m_timeValue;
+    int32_t m_timeScale;
+    uint32_t m_timeFlags;
+};
+
+WTF_EXPORT_PRIVATE extern MediaTime abs(const MediaTime& rhs);
+}
+
+using WTF::MediaTime;
+using WTF::abs;
index de6e96e2d83be470a56924511493426b7bcda86b..1be026d2602b06709a805c460f1207ba51ef21d9 100644 (file)
@@ -1,3 +1,21 @@
+2012-07-27  Jer Noble  <jer.noble@apple.com>
+
+        Support a rational time class for use by media elements.
+        https://bugs.webkit.org/show_bug.cgi?id=88787
+
+        Add unit tests for the WTF::MediaTime class.
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/GNUmakefile.am:
+        * TestWebKitAPI/TestWebKitAPI.gypi:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/MediaTime.cpp: Added.
+        * TestWebKitAPI/win/TestWebKitAPI.vcproj:
+        (WTF::operator<<):
+        (TestWebKitAPI):
+        (TestWebKitAPI::TEST):
+
 2012-07-27  Balazs Kelemen  <kbalazs@webkit.org>
 
         [NRWT] should have a way to restrict pixel tests for individual directories
index f795743786793002208cc883d9aa8d68248485cd..815c43bafcade8b9deb1148793ba1d44a0951c73 100644 (file)
@@ -53,6 +53,7 @@ Programs_TestWebKitAPI_TestWTF_SOURCES = \
        Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp \
        Tools/TestWebKitAPI/Tests/WTF/Functional.cpp \
        Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp \
+       Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp \
        Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp \
        Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp \
        Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp \
index c51187fa06360a291482375a30618419717b6ce7..941e776d5f4d01e9b3937ca8ce47f9dd77f45ef7 100644 (file)
@@ -34,6 +34,7 @@
             'Tests/WTF/CheckedArithmeticOperations.cpp',
             'Tests/WTF/Functional.cpp',
             'Tests/WTF/HashMap.cpp',
+            'Tests/WTF/MediaTime.cpp',
             'Tests/WTF/RedBlackTree.cpp',
             'Tests/WTF/StringBuilder.cpp',
             'Tests/WTF/StringOperators.cpp',
index d86f4b9a55257915a33ae9672bb5b2dcf91bf335..d3664a129dd59dd15cf2c958f99c1c168911c2c3 100644 (file)
                C540F784152E5A9A00A40C8C /* verboseMarkup.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C540F783152E5A7800A40C8C /* verboseMarkup.html */; };
                E1220DA0155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */; };
                E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */; };
+               CD5497B415857F0C00B5BC30 /* MediaTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD5497B315857F0C00B5BC30 /* MediaTime.cpp */; };
                E490296814E2E3A4002BEDD1 /* TypingStyleCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */; };
                F3FC3EE313678B7300126A65 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3FC3EE213678B7300126A65 /* libgtest.a */; };
                F660AA0D15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */; };
                C540F783152E5A7800A40C8C /* verboseMarkup.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = verboseMarkup.html; sourceTree = "<group>"; };
                E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryCacheDisableWithinResourceLoadDelegate.mm; sourceTree = "<group>"; };
                E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = MemoryCacheDisableWithinResourceLoadDelegate.html; sourceTree = "<group>"; };
+               CD5497B315857F0C00B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MediaTime.cpp; path = WTF/MediaTime.cpp; sourceTree = "<group>"; };
                E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TypingStyleCrash.mm; sourceTree = "<group>"; };
                F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
                F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetInjectedBundleInitializationUserDataCallback.cpp; sourceTree = "<group>"; };
                        children = (
                                BC029B1A1486B23800817DA9 /* ns */,
                                C0991C4F143C7D68007998F2 /* cf */,
+                               CD5497B315857F0C00B5BC30 /* MediaTime.cpp */,
                                0FC6C4CE141034AD005B7F0C /* MetaAllocator.cpp */,
                                0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
                                A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
                                A5E2027315B2181900C13E14 /* WindowlessWebViewWithMedia.mm in Sources */,
                                26B2DFF915BDE599004F691D /* HashSet.cpp in Sources */,
                                00CD9F6315BE312C002DA2CE /* BackForwardList.mm in Sources */,
+                               CD5497B415857F0C00B5BC30 /* MediaTime.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp b/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
new file mode 100644 (file)
index 0000000..700fb63
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if PLATFORM(WIN)
+#define _USE_MATH_DEFINES
+#endif
+
+#include <wtf/MediaTime.h>
+
+using namespace std;
+
+#if PLATFORM(WIN)
+// Work around Visual Studio 2008's lack of an INFINITY or NAN definition.
+#include <limits>
+#if !defined(INFINITY)
+#define INFINITY (numeric_limits<double>::infinity())
+#endif
+#if !defined(NAN)
+#define NAN (numeric_limits<double>::quiet_NaN())
+#endif
+#endif
+
+namespace WTF {
+
+std::ostream& operator<<(std::ostream& out, const MediaTime& val)
+{
+    out << "{ ";
+    if (val.isInvalid())
+        out << "invalid";
+    else if (val.isPositiveInfinite())
+        out << "+infinite";
+    else if (val.isNegativeInfinite())
+        out << "-infinite";
+    else
+        out << "value: " << val.timeValue() << ", scale: " << val.timeScale();
+    return out << " }";
+}
+
+}
+
+namespace TestWebKitAPI {
+
+TEST(WTF, MediaTime)
+{
+    // Comparison Operators
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() > MediaTime::negativeInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() < MediaTime::positiveInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() == MediaTime::negativeInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() == MediaTime::positiveInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::invalidTime() == MediaTime::invalidTime(), true);
+    EXPECT_EQ(MediaTime::invalidTime() > MediaTime::negativeInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::invalidTime() > MediaTime::positiveInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() < MediaTime::invalidTime(), true);
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() < MediaTime::invalidTime(), true);
+    EXPECT_EQ(MediaTime::indefiniteTime() == MediaTime::indefiniteTime(), true);
+    EXPECT_EQ(MediaTime::indefiniteTime() > MediaTime::negativeInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::indefiniteTime() < MediaTime::positiveInfiniteTime(), true);
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() < MediaTime::indefiniteTime(), true);
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() > MediaTime::indefiniteTime(), true);
+    EXPECT_EQ(MediaTime(1, 1) < MediaTime::indefiniteTime(), true);
+    EXPECT_EQ(MediaTime::indefiniteTime() > MediaTime(1, 1), true);
+    EXPECT_EQ(MediaTime(1, 1) < MediaTime(2, 1), true);
+    EXPECT_EQ(MediaTime(2, 1) > MediaTime(1, 1), true);
+    EXPECT_EQ(MediaTime(2, 1) == MediaTime(2, 1), true);
+    EXPECT_EQ(MediaTime(2, 1) == MediaTime(4, 2), true);
+
+    // Addition Operators
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() + MediaTime::positiveInfiniteTime(), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() + MediaTime::negativeInfiniteTime(), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() + MediaTime::negativeInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() + MediaTime::positiveInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() + MediaTime::positiveInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() + MediaTime::negativeInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() + MediaTime::invalidTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() + MediaTime(1, 1), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() + MediaTime::positiveInfiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() + MediaTime::negativeInfiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() + MediaTime::indefiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() + MediaTime(1, 1), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime(1, 1) + MediaTime(1, 1), MediaTime(2, 1));
+    EXPECT_EQ(MediaTime(1, 2) + MediaTime(1, 3), MediaTime(5, 6));
+    EXPECT_EQ(MediaTime(1, numeric_limits<int32_t>::max()-1) + MediaTime(1, numeric_limits<int32_t>::max()-2), MediaTime(2, numeric_limits<int32_t>::max()));
+
+    // Subtraction Operators
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() - MediaTime::positiveInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() - MediaTime::negativeInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::positiveInfiniteTime() - MediaTime::negativeInfiniteTime(), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::negativeInfiniteTime() - MediaTime::positiveInfiniteTime(), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::invalidTime() - MediaTime::positiveInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() - MediaTime::negativeInfiniteTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() - MediaTime::invalidTime(), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::invalidTime() - MediaTime(1, 1), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() - MediaTime::positiveInfiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() - MediaTime::negativeInfiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() - MediaTime::indefiniteTime(), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime::indefiniteTime() - MediaTime(1, 1), MediaTime::indefiniteTime());
+    EXPECT_EQ(MediaTime(3, 1) - MediaTime(2, 1), MediaTime(1, 1));
+    EXPECT_EQ(MediaTime(1, 2) - MediaTime(1, 3), MediaTime(1, 6));
+    EXPECT_EQ(MediaTime(2, numeric_limits<int32_t>::max()-1) - MediaTime(1, numeric_limits<int32_t>::max()-2), MediaTime(1, numeric_limits<int32_t>::max()));
+
+    // Constants
+    EXPECT_EQ(MediaTime::zeroTime(), MediaTime(0, 1));
+    EXPECT_EQ(MediaTime::invalidTime(), MediaTime(-1, 1, 0));
+    EXPECT_EQ(MediaTime::positiveInfiniteTime(), MediaTime(0, 1, MediaTime::PositiveInfinite));
+    EXPECT_EQ(MediaTime::negativeInfiniteTime(), MediaTime(0, 1, MediaTime::NegativeInfinite));
+    EXPECT_EQ(MediaTime::indefiniteTime(), MediaTime(0, 1, MediaTime::Indefinite));
+
+    // Absolute Functions
+    EXPECT_EQ(abs(MediaTime::positiveInfiniteTime()), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(abs(MediaTime::negativeInfiniteTime()), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(abs(MediaTime::invalidTime()), MediaTime::invalidTime());
+    EXPECT_EQ(abs(MediaTime(1, 1)), MediaTime(1, 1));
+    EXPECT_EQ(abs(MediaTime(-1, 1)), MediaTime(1, 1));
+    EXPECT_EQ(abs(MediaTime(-1, -1)), MediaTime(-1, -1));
+    EXPECT_EQ(abs(MediaTime(1, -1)), MediaTime(-1, -1));
+
+    // Floating Point Functions
+    EXPECT_EQ(MediaTime::createWithFloat(1.0f), MediaTime(1, 1));
+    EXPECT_EQ(MediaTime::createWithFloat(1.5f), MediaTime(3, 2));
+    EXPECT_EQ(MediaTime::createWithDouble(1.0), MediaTime(1, 1));
+    EXPECT_EQ(MediaTime::createWithDouble(1.5), MediaTime(3, 2));
+    EXPECT_EQ(MediaTime(1, 1).toFloat(), 1.0f);
+    EXPECT_EQ(MediaTime(3, 2).toFloat(), 1.5f);
+    EXPECT_EQ(MediaTime(1, 1).toDouble(), 1.0);
+    EXPECT_EQ(MediaTime(3, 2).toDouble(), 1.5);
+    EXPECT_EQ(MediaTime(1, 1 << 16).toFloat(), 1 / pow(2.0f, 16.0f));
+    EXPECT_EQ(MediaTime(1, 1 << 30).toDouble(), 1 / pow(2.0, 30.0));
+    EXPECT_EQ(MediaTime::createWithDouble(M_PI, 1 << 30), MediaTime(3373259426, 1 << 30));
+    EXPECT_EQ(MediaTime::createWithFloat(INFINITY), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithFloat(-INFINITY), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithFloat(NAN), MediaTime::invalidTime());
+    EXPECT_EQ(MediaTime::createWithDouble(INFINITY), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithDouble(-INFINITY), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithDouble(NAN), MediaTime::invalidTime());
+
+    // Overflow Behavior
+    EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 64.0f)), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithFloat(-pow(2.0f, 64.0f)), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 2).timeScale(), 1);
+    EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 3).timeScale(), 1);
+    EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 64.0)), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithDouble(-pow(2.0, 64.0)), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 2).timeScale(), 1);
+    EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 3).timeScale(), 1);
+    EXPECT_EQ((MediaTime(numeric_limits<int64_t>::max(), 2) + MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
+    EXPECT_EQ((MediaTime(numeric_limits<int64_t>::min(), 2) - MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::max(), 1) + MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) + MediaTime(numeric_limits<int64_t>::min(), 1), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) - MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::negativeInfiniteTime());
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::max(), 1) - MediaTime(numeric_limits<int64_t>::min(), 1), MediaTime::positiveInfiniteTime());
+}
+
+}
+
index 000f15e18bc1aad0876f40ed9e7252c578fa7230..a941cd6868b4f0563240761a5266962ff85346d2 100644 (file)
                                        RelativePath="..\Tests\WTF\HashMap.cpp"
                                        >
                                </File>
+                               <File
+                                       RelativePath="..\Tests\WTF\MediaTime.cpp"
+                                       >
+                               </File>
                                <File
                                        RelativePath="..\Tests\WTF\StringOperators.cpp"
                                        >