Title: [213068] trunk
Revision
213068
Author
[email protected]
Date
2017-02-27 08:53:05 -0800 (Mon, 27 Feb 2017)

Log Message

Add public method to MediaTime for doing timeScale conversion.
https://bugs.webkit.org/show_bug.cgi?id=168860

Reviewed by Eric Carlson.

Source/WTF:

The newly public method, modeled on CMTimeConvertScale, allows callers to specify what rounding technique
will be used when converting to a new time scale.

* wtf/MediaTime.cpp:
(WTF::MediaTime::toTimeScale):
(WTF::MediaTime::setTimeScale):
* wtf/MediaTime.h:

Tools:

* TestWebKitAPI/Tests/WTF/MediaTime.cpp:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (213067 => 213068)


--- trunk/Source/WTF/ChangeLog	2017-02-27 16:52:46 UTC (rev 213067)
+++ trunk/Source/WTF/ChangeLog	2017-02-27 16:53:05 UTC (rev 213068)
@@ -1,3 +1,18 @@
+2017-02-24  Jer Noble  <[email protected]>
+
+        Add public method to MediaTime for doing timeScale conversion.
+        https://bugs.webkit.org/show_bug.cgi?id=168860
+
+        Reviewed by Eric Carlson.
+
+        The newly public method, modeled on CMTimeConvertScale, allows callers to specify what rounding technique
+        will be used when converting to a new time scale.
+
+        * wtf/MediaTime.cpp:
+        (WTF::MediaTime::toTimeScale):
+        (WTF::MediaTime::setTimeScale):
+        * wtf/MediaTime.h:
+
 2017-02-26  Myles C. Maxfield  <[email protected]>
 
         Stop compiling our own cursorMovementIterator()

Modified: trunk/Source/WTF/wtf/MediaTime.cpp (213067 => 213068)


--- trunk/Source/WTF/wtf/MediaTime.cpp	2017-02-27 16:52:46 UTC (rev 213067)
+++ trunk/Source/WTF/wtf/MediaTime.cpp	2017-02-27 16:53:05 UTC (rev 213068)
@@ -470,8 +470,15 @@
     return *time;
 }
 
-void MediaTime::setTimeScale(uint32_t timeScale)
+MediaTime MediaTime::toTimeScale(uint32_t timeScale, RoundingFlags flags) const
 {
+    MediaTime result = *this;
+    result.setTimeScale(timeScale, flags);
+    return result;
+}
+
+void MediaTime::setTimeScale(uint32_t timeScale, RoundingFlags flags)
+{
     if (hasDoubleValue()) {
         *this = MediaTime::createWithDouble(m_timeValueAsDouble, timeScale);
         return;
@@ -479,19 +486,76 @@
 
     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, static_cast<int64_t>(timeScale), newWholePart))
-        timeScale /= 2;
+    int64_t newValue = 0;
+    int64_t remainder = 0;
+    if (safeMultiply(m_timeValue, static_cast<int64_t>(timeScale), newValue)) {
+        remainder = newValue % m_timeScale;
+        newValue = newValue / m_timeScale;
+    } else {
+        int64_t highPart = (m_timeValue >> 32) * timeScale;
+        int64_t highRemainder = highPart % m_timeScale;
+        highPart /= m_timeScale;
 
-    int64_t remainder = m_timeValue % m_timeScale;
-    m_timeValue = newWholePart + (remainder * timeScale) / m_timeScale;
-    m_timeScale = timeScale;
+        int64_t lowPart = (m_timeValue & 0xFFFFFFFF) * timeScale + highRemainder;
+        highPart += (lowPart >> 32);
+        lowPart &= 0xFFFFFFFF;
+        remainder = lowPart % m_timeScale;
+        lowPart /= m_timeScale;
+
+        if (highPart < std::numeric_limits<int32_t>::min()) {
+            *this = negativeInfiniteTime();
+            return;
+        }
+
+        if (highPart > std::numeric_limits<int32_t>::max()) {
+            *this = positiveInfiniteTime();
+            return;
+        }
+
+        newValue = (highPart << 32) + lowPart;
+    }
+
+    m_timeValue = newValue;
+    std::swap(m_timeScale, timeScale);
+
+    if (!remainder)
+        return;
+
+    m_timeFlags |= HasBeenRounded;
+    switch (flags) {
+    case RoundingFlags::HalfAwayFromZero:
+        if (static_cast<int64_t>(llabs(remainder)) * 2 >= static_cast<int64_t>(timeScale)) {
+            // round up (away from zero)
+            if (remainder < 0)
+                m_timeValue--;
+            else
+                m_timeValue++;
+        }
+        break;
+
+    case RoundingFlags::TowardZero:
+        break;
+
+    case RoundingFlags::AwayFromZero:
+        if (remainder < 0)
+            m_timeValue--;
+        else
+            m_timeValue++;
+        break;
+
+    case RoundingFlags::TowardPositiveInfinity:
+        if (remainder > 0)
+            m_timeValue++;
+        break;
+        
+    case RoundingFlags::TowardNegativeInfinity:
+        if (remainder < 0)
+            m_timeValue--;
+        break;
+    }
 }
 
 void MediaTime::dump(PrintStream &out) const

Modified: trunk/Source/WTF/wtf/MediaTime.h (213067 => 213068)


--- trunk/Source/WTF/wtf/MediaTime.h	2017-02-27 16:52:46 UTC (rev 213067)
+++ trunk/Source/WTF/wtf/MediaTime.h	2017-02-27 16:53:05 UTC (rev 213068)
@@ -120,8 +120,18 @@
     static const uint32_t DefaultTimeScale = 10000000;
     static const uint32_t MaximumTimeScale;
 
+    enum class RoundingFlags {
+        HalfAwayFromZero = 0,
+        TowardZero,
+        AwayFromZero,
+        TowardPositiveInfinity,
+        TowardNegativeInfinity,
+    };
+
+    MediaTime toTimeScale(uint32_t, RoundingFlags = RoundingFlags::HalfAwayFromZero) const;
+
 private:
-    void setTimeScale(uint32_t);
+    void setTimeScale(uint32_t, RoundingFlags = RoundingFlags::HalfAwayFromZero);
 
     union {
         int64_t m_timeValue;

Modified: trunk/Tools/ChangeLog (213067 => 213068)


--- trunk/Tools/ChangeLog	2017-02-27 16:52:46 UTC (rev 213067)
+++ trunk/Tools/ChangeLog	2017-02-27 16:53:05 UTC (rev 213068)
@@ -1,3 +1,13 @@
+2017-02-24  Jer Noble  <[email protected]>
+
+        Add public method to MediaTime for doing timeScale conversion.
+        https://bugs.webkit.org/show_bug.cgi?id=168860
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/Tests/WTF/MediaTime.cpp:
+        (TestWebKitAPI::TEST):
+
 2017-02-26  Wenson Hsieh  <[email protected]>
 
         Unreviewed, revert all temporary build fixes for data interaction

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp (213067 => 213068)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp	2017-02-27 16:52:46 UTC (rev 213067)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp	2017-02-27 16:53:05 UTC (rev 213068)
@@ -212,6 +212,73 @@
     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());
+
+    // Rounding
+    EXPECT_EQ(MediaTime(1, 1).toTimeScale(2).timeValue(), 2);
+    EXPECT_EQ(MediaTime(1, 3).toTimeScale(6).timeValue(), 2);
+    EXPECT_EQ(MediaTime(2, 2).toTimeScale(1).timeValue(), 1);
+    EXPECT_EQ(MediaTime(2, 6).toTimeScale(3).timeValue(), 1);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1).hasBeenRounded(), true);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(51, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(49, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(3, 2).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 2);
+    EXPECT_EQ(MediaTime(151, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 2);
+    EXPECT_EQ(MediaTime(149, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-51, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-49, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-3, 2).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-151, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-149, 100).toTimeScale(1, MediaTime::RoundingFlags::HalfAwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-51, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-49, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), 1);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(3, 2).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), 2);
+    EXPECT_EQ(MediaTime(151, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), 2);
+    EXPECT_EQ(MediaTime(149, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), 2);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-51, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-49, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-3, 2).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-151, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-149, 100).toTimeScale(1, MediaTime::RoundingFlags::AwayFromZero).timeValue(), -2);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 1);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 0);
+    EXPECT_EQ(MediaTime(3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 2);
+    EXPECT_EQ(MediaTime(151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 2);
+    EXPECT_EQ(MediaTime(149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 2);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-51, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-49, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardPositiveInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), 0);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), 1);
+    EXPECT_EQ(MediaTime(151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), 1);
+    EXPECT_EQ(MediaTime(149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), 1);
+    EXPECT_EQ(MediaTime(-1, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-51, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-49, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -1);
+    EXPECT_EQ(MediaTime(-3, 2).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-151, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -2);
+    EXPECT_EQ(MediaTime(-149, 100).toTimeScale(1, MediaTime::RoundingFlags::TowardNegativeInfinity).timeValue(), -2);
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::max(), 1).toTimeScale(2), MediaTime::positiveInfiniteTime());
+    EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1).toTimeScale(2), MediaTime::negativeInfiniteTime());
+    int64_t maxInt32 = numeric_limits<int32_t>::max();
+    EXPECT_EQ(MediaTime(maxInt32 * 2, 1).toTimeScale(2).timeValue(), maxInt32 * 4);
 }
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to