<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[198646] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/198646">198646</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2016-03-24 15:27:45 -0700 (Thu, 24 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE] Make calling HTMLMediaElement.buffered less expensive
https://bugs.webkit.org/show_bug.cgi?id=155846

Reviewed by Eric Carlson.

The MSE specification requires a new TimeRanges object be returned when calling
HTMLMediaElement.buffered. Additionally, the requirements for generating the buffered time
ranges for MediaSource and its constituent SourceBuffers are specific and expensive. Rather
than perform all these steps each time HTMLMediaElement.buffered is queried, cache the final
result and only regenerate the cached value if the buffered ranges of the consituent
SourceBuffers has changed.

Also, make copying a PlatformTimeRanges more efficient by doing a straight vector-to-vector
copy of the PlatformTimeRange's data.

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::buffered):
(WebCore::MediaSource::regenerateActiveSourceBuffers):
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::removeCodedFrames):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
* Modules/mediasource/SourceBuffer.h:
* platform/graphics/PlatformTimeRanges.cpp:
(WebCore::PlatformTimeRanges::PlatformTimeRanges): Deleted.
(WebCore::PlatformTimeRanges::operator=): Deleted.
(WebCore::PlatformTimeRanges::copy): Deleted.
* platform/graphics/PlatformTimeRanges.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceMediaSourcecpp">trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceMediaSourceh">trunk/Source/WebCore/Modules/mediasource/MediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBuffercpp">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBufferh">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPlatformTimeRangescpp">trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPlatformTimeRangesh">trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/ChangeLog        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -1,5 +1,36 @@
</span><span class="cx"> 2016-03-24  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [MSE] Make calling HTMLMediaElement.buffered less expensive
+        https://bugs.webkit.org/show_bug.cgi?id=155846
+
+        Reviewed by Eric Carlson.
+
+        The MSE specification requires a new TimeRanges object be returned when calling
+        HTMLMediaElement.buffered. Additionally, the requirements for generating the buffered time
+        ranges for MediaSource and its constituent SourceBuffers are specific and expensive. Rather
+        than perform all these steps each time HTMLMediaElement.buffered is queried, cache the final
+        result and only regenerate the cached value if the buffered ranges of the consituent
+        SourceBuffers has changed.
+
+        Also, make copying a PlatformTimeRanges more efficient by doing a straight vector-to-vector
+        copy of the PlatformTimeRange's data.
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::buffered):
+        (WebCore::MediaSource::regenerateActiveSourceBuffers):
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::removeCodedFrames):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
+        * Modules/mediasource/SourceBuffer.h:
+        * platform/graphics/PlatformTimeRanges.cpp:
+        (WebCore::PlatformTimeRanges::PlatformTimeRanges): Deleted.
+        (WebCore::PlatformTimeRanges::operator=): Deleted.
+        (WebCore::PlatformTimeRanges::copy): Deleted.
+        * platform/graphics/PlatformTimeRanges.h:
+
+2016-03-24  Jer Noble  &lt;jer.noble@apple.com&gt;
+
</ins><span class="cx">         REGRESSION(r189129): &lt;audio&gt; elements do not have playback controls on iOS.
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=155808
</span><span class="cx">         &lt;rdar://problem/23822457&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -141,13 +141,20 @@
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;PlatformTimeRanges&gt; MediaSource::buffered() const
</span><span class="cx"> {
</span><ins>+    if (m_buffered &amp;&amp; m_activeSourceBuffers-&gt;length() &amp;&amp; std::all_of(m_activeSourceBuffers-&gt;begin(), m_activeSourceBuffers-&gt;end(), [] (RefPtr&lt;SourceBuffer&gt;&amp; buffer) { return !buffer-&gt;isBufferedDirty(); }))
+        return std::make_unique&lt;PlatformTimeRanges&gt;(*m_buffered);
+
+    m_buffered = std::make_unique&lt;PlatformTimeRanges&gt;();
+    for (auto&amp; sourceBuffer : *m_activeSourceBuffers)
+        sourceBuffer-&gt;setBufferedDirty(false);
+
</ins><span class="cx">     // Implements MediaSource algorithm for HTMLMediaElement.buffered.
</span><span class="cx">     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions
</span><span class="cx">     Vector&lt;PlatformTimeRanges&gt; activeRanges = this-&gt;activeRanges();
</span><span class="cx"> 
</span><span class="cx">     // 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps.
</span><span class="cx">     if (activeRanges.isEmpty())
</span><del>-        return std::make_unique&lt;PlatformTimeRanges&gt;();
</del><ins>+        return std::make_unique&lt;PlatformTimeRanges&gt;(*m_buffered);
</ins><span class="cx"> 
</span><span class="cx">     // 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers.
</span><span class="cx">     // 3. Let highest end time be the largest range end time in the active ranges.
</span><span class="lines">@@ -160,10 +167,10 @@
</span><span class="cx"> 
</span><span class="cx">     // Return an empty range if all ranges are empty.
</span><span class="cx">     if (!highestEndTime)
</span><del>-        return std::make_unique&lt;PlatformTimeRanges&gt;();
</del><ins>+        return std::make_unique&lt;PlatformTimeRanges&gt;(*m_buffered);
</ins><span class="cx"> 
</span><span class="cx">     // 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time.
</span><del>-    PlatformTimeRanges intersectionRanges(MediaTime::zeroTime(), highestEndTime);
</del><ins>+    m_buffered-&gt;add(MediaTime::zeroTime(), highestEndTime);
</ins><span class="cx"> 
</span><span class="cx">     // 5. For each SourceBuffer object in activeSourceBuffers run the following steps:
</span><span class="cx">     bool ended = readyState() == endedKeyword();
</span><span class="lines">@@ -175,10 +182,10 @@
</span><span class="cx"> 
</span><span class="cx">         // 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges.
</span><span class="cx">         // 5.4 Replace the ranges in intersection ranges with the new intersection ranges.
</span><del>-        intersectionRanges.intersectWith(sourceRanges);
</del><ins>+        m_buffered-&gt;intersectWith(sourceRanges);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return std::make_unique&lt;PlatformTimeRanges&gt;(intersectionRanges);
</del><ins>+    return std::make_unique&lt;PlatformTimeRanges&gt;(*m_buffered);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaSource::seekToTime(const MediaTime&amp; time)
</span><span class="lines">@@ -914,6 +921,8 @@
</span><span class="cx">             newList.append(sourceBuffer);
</span><span class="cx">     }
</span><span class="cx">     m_activeSourceBuffers-&gt;swap(newList);
</span><ins>+    for (auto&amp; sourceBuffer : *m_activeSourceBuffers)
+        sourceBuffer-&gt;setBufferedDirty(true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.h (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/MediaSource.h        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.h        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx">     RefPtr&lt;MediaSourcePrivate&gt; m_private;
</span><span class="cx">     RefPtr&lt;SourceBufferList&gt; m_sourceBuffers;
</span><span class="cx">     RefPtr&lt;SourceBufferList&gt; m_activeSourceBuffers;
</span><ins>+    mutable std::unique_ptr&lt;PlatformTimeRanges&gt; m_buffered;
</ins><span class="cx">     HTMLMediaElement* m_mediaElement;
</span><span class="cx">     MediaTime m_duration;
</span><span class="cx">     MediaTime m_pendingSeekTime;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -795,6 +795,7 @@
</span><span class="cx"> 
</span><span class="cx">         erasedRanges-&gt;invert();
</span><span class="cx">         m_buffered-&gt;intersectWith(*erasedRanges);
</span><ins>+        setBufferedDirty(true);
</ins><span class="cx"> 
</span><span class="cx">         // 3.4 If this object is in activeSourceBuffers, the current playback position is greater than or equal to start
</span><span class="cx">         // and less than the remove end timestamp, and HTMLMediaElement.readyState is greater than HAVE_METADATA, then set
</span><span class="lines">@@ -1605,6 +1606,7 @@
</span><span class="cx"> 
</span><span class="cx">             erasedRanges-&gt;invert();
</span><span class="cx">             m_buffered-&gt;intersectWith(*erasedRanges);
</span><ins>+            setBufferedDirty(true);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // 1.17 If spliced audio frame is set:
</span><span class="lines">@@ -1645,6 +1647,7 @@
</span><span class="cx"> 
</span><span class="cx">         m_buffered-&gt;add(presentationTimestamp.toDouble(), (presentationTimestamp + frameDuration + microsecond).toDouble());
</span><span class="cx">         m_bufferedSinceLastMonitor += frameDuration.toDouble();
</span><ins>+        setBufferedDirty(true);
</ins><span class="cx"> 
</span><span class="cx">         break;
</span><span class="cx">     } while (1);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -125,6 +125,9 @@
</span><span class="cx"> 
</span><span class="cx">     void rangeRemoval(const MediaTime&amp;, const MediaTime&amp;);
</span><span class="cx"> 
</span><ins>+    bool isBufferedDirty() const { return m_bufferedDirty; }
+    void setBufferedDirty(bool flag) { m_bufferedDirty = flag; }
+
</ins><span class="cx">     // ActiveDOMObject API.
</span><span class="cx">     bool hasPendingActivity() const override;
</span><span class="cx"> 
</span><span class="lines">@@ -225,6 +228,7 @@
</span><span class="cx"> 
</span><span class="cx">     HashMap&lt;AtomicString, TrackBuffer&gt; m_trackBufferMap;
</span><span class="cx">     RefPtr&lt;TimeRanges&gt; m_buffered;
</span><ins>+    bool m_bufferedDirty { true };
</ins><span class="cx"> 
</span><span class="cx">     enum AppendStateType { WaitingForSegment, ParsingInitSegment, ParsingMediaSegment };
</span><span class="cx">     AppendStateType m_appendState;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPlatformTimeRangescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.cpp (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.cpp        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.cpp        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -36,25 +36,6 @@
</span><span class="cx">     add(start, end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PlatformTimeRanges::PlatformTimeRanges(const PlatformTimeRanges&amp; other)
-{
-    copy(other);
-}
-
-PlatformTimeRanges&amp; PlatformTimeRanges::operator=(const PlatformTimeRanges&amp; other)
-{
-    return copy(other);
-}
-
-PlatformTimeRanges&amp; PlatformTimeRanges::copy(const PlatformTimeRanges&amp; other)
-{
-    unsigned size = other.m_ranges.size();
-    for (unsigned i = 0; i &lt; size; i++)
-        add(other.m_ranges[i].m_start, other.m_ranges[i].m_end);
-    
-    return *this;
-}
-
</del><span class="cx"> void PlatformTimeRanges::invert()
</span><span class="cx"> {
</span><span class="cx">     PlatformTimeRanges inverted;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPlatformTimeRangesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.h (198645 => 198646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.h        2016-03-24 22:20:52 UTC (rev 198645)
+++ trunk/Source/WebCore/platform/graphics/PlatformTimeRanges.h        2016-03-24 22:27:45 UTC (rev 198646)
</span><span class="lines">@@ -42,10 +42,7 @@
</span><span class="cx"> public:
</span><span class="cx">     explicit PlatformTimeRanges() { }
</span><span class="cx">     PlatformTimeRanges(const MediaTime&amp; start, const MediaTime&amp; end);
</span><del>-    PlatformTimeRanges(const PlatformTimeRanges&amp;);
</del><span class="cx"> 
</span><del>-    PlatformTimeRanges&amp; operator=(const PlatformTimeRanges&amp;);
-
</del><span class="cx">     MediaTime start(unsigned index) const;
</span><span class="cx">     MediaTime start(unsigned index, bool&amp; valid) const;
</span><span class="cx">     MediaTime end(unsigned index) const;
</span><span class="lines">@@ -72,8 +69,6 @@
</span><span class="cx">     void dump(WTF::PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    PlatformTimeRanges&amp; copy(const PlatformTimeRanges&amp;);
-
</del><span class="cx">     // We consider all the Ranges to be semi-bounded as follow: [start, end[
</span><span class="cx">     struct Range {
</span><span class="cx">         Range() { }
</span></span></pre>
</div>
</div>

</body>
</html>