<!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>[166423] trunk</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/166423">166423</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2014-03-28 13:08:51 -0700 (Fri, 28 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE] Implement support for SourceBuffer.remove()
https://bugs.webkit.org/show_bug.cgi?id=121562

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/media-source/media-source-remove.html

Add support for SourceBuffer.remove().

* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::SourceBuffer): Initialize new member variables.
(WebCore::SourceBuffer::setTimestampOffset): Update comments to match spec.
(WebCore::SourceBuffer::remove): Added; start removeTimer.
(WebCore::SourceBuffer::abortIfUpdating): Cancel removeTimer.
(WebCore::SourceBuffer::removedFromMediaSource): Call abortIfUpdating().
(WebCore::SourceBuffer::stop): Cancel removeTimer.
(WebCore::SourceBuffer::removeCodedFrames): Added.
(WebCore::SourceBuffer::removeTimerFired): Added.
* Modules/mediasource/SourceBuffer.h:
* Modules/mediasource/SourceBuffer.idl:

LayoutTests:

* media/media-source/media-source-remove-expected.txt: Added.
* media/media-source/media-source-remove.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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="#trunkSourceWebCoreModulesmediasourceSourceBufferidl">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.idl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourceremoveexpectedtxt">trunk/LayoutTests/media/media-source/media-source-remove-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourceremovehtml">trunk/LayoutTests/media/media-source/media-source-remove.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (166422 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-03-28 19:57:34 UTC (rev 166422)
+++ trunk/LayoutTests/ChangeLog        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-03-28  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Implement support for SourceBuffer.remove()
+        https://bugs.webkit.org/show_bug.cgi?id=121562
+
+        Reviewed by Eric Carlson.
+
+        * media/media-source/media-source-remove-expected.txt: Added.
+        * media/media-source/media-source-remove.html: Added.
+
</ins><span class="cx"> 2014-03-28  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clear SVGInlineTextBox fragments when the text changes.
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourceremoveexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-remove-expected.txt (0 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-remove-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-remove-expected.txt        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+This tests the SourceBuffer.remove() API. The test will remove samples from the given startTime (0) up to but not including the presentation start time of the sync sample (4) after endTime (2).
+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;))
+RUN(sourceBuffer.appendBuffer(initSegment))
+EVENT(updateend)
+RUN(sourceBuffer.appendBuffer(samples))
+EVENT(updateend)
+RUN(sourceBuffer.remove(0, 2))
+EVENT(updateend)
+EXPECTED (sourceBuffer.buffered.start(0).toFixed(1) == '4') OK
+END OF TEST
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourceremovehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-remove.html (0 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-remove.html                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-remove.html        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;title&gt;mock-media-source&lt;/title&gt;
+    &lt;script src=&quot;mock-media-source.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;../video-test.js&quot;&gt;&lt;/script&gt;
+    &lt;script&gt;
+    var source;
+    var sourceBuffer;
+    var initSegment;
+
+    if (window.internals)
+        internals.initializeMockMediaSource();
+
+    function runTest() {
+        findMediaElement();
+
+        source = new MediaSource();
+        waitForEventOn(source, 'sourceopen', sourceOpen);
+        run('video.src = URL.createObjectURL(source)');
+    }
+
+    function sourceOpen() {
+        run('sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;)');
+        waitForEventOn(sourceBuffer, 'updateend', loadSamples, false, true);
+        initSegment = makeAInit(8, [makeATrack(1, 'mock', TRACK_KIND.VIDEO)]);
+        run('sourceBuffer.appendBuffer(initSegment)');
+    }
+
+    function loadSamples() {
+        samples = concatenateSamples([
+            makeASample(0, 0, 1, 1, SAMPLE_FLAG.SYNC),
+            makeASample(1, 1, 1, 1, SAMPLE_FLAG.NONE),
+            makeASample(2, 2, 1, 1, SAMPLE_FLAG.NONE),
+            makeASample(3, 3, 1, 1, SAMPLE_FLAG.NONE),
+            makeASample(4, 4, 1, 1, SAMPLE_FLAG.SYNC),
+            makeASample(5, 5, 1, 1, SAMPLE_FLAG.NONE),
+            makeASample(6, 6, 1, 1, SAMPLE_FLAG.NONE),
+            makeASample(7, 7, 1, 1, SAMPLE_FLAG.NONE),
+        ]);
+        waitForEventOn(sourceBuffer, 'updateend', remove, false, true);
+        run('sourceBuffer.appendBuffer(samples)');
+    }
+
+    function remove() {
+        waitForEventOn(sourceBuffer, 'updateend', checkRemoved, false, true);
+        run('sourceBuffer.remove(0, 2)');
+    }
+
+    function checkRemoved() {
+        testExpected('sourceBuffer.buffered.start(0).toFixed(1)', 4);
+        endTest();
+    }
+
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;div&gt;This tests the SourceBuffer.remove() API. The test will remove samples from the given startTime (0) up to but not including the presentation start time of the sync sample (4) after endTime (2).&lt;/div&gt;
+    &lt;video&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (166422 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-03-28 19:57:34 UTC (rev 166422)
+++ trunk/Source/WebCore/ChangeLog        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2014-03-28  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Implement support for SourceBuffer.remove()
+        https://bugs.webkit.org/show_bug.cgi?id=121562
+
+        Reviewed by Eric Carlson.
+
+        Test: media/media-source/media-source-remove.html
+
+        Add support for SourceBuffer.remove().
+
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::SourceBuffer): Initialize new member variables.
+        (WebCore::SourceBuffer::setTimestampOffset): Update comments to match spec.
+        (WebCore::SourceBuffer::remove): Added; start removeTimer.
+        (WebCore::SourceBuffer::abortIfUpdating): Cancel removeTimer.
+        (WebCore::SourceBuffer::removedFromMediaSource): Call abortIfUpdating().
+        (WebCore::SourceBuffer::stop): Cancel removeTimer.
+        (WebCore::SourceBuffer::removeCodedFrames): Added.
+        (WebCore::SourceBuffer::removeTimerFired): Added.
+        * Modules/mediasource/SourceBuffer.h:
+        * Modules/mediasource/SourceBuffer.idl:
+
</ins><span class="cx"> 2014-03-27  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Support form controls that may need incremental redraw
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (166422 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-03-28 19:57:34 UTC (rev 166422)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -103,6 +103,9 @@
</span><span class="cx">     , m_timeOfBufferingMonitor(monotonicallyIncreasingTime())
</span><span class="cx">     , m_bufferedSinceLastMonitor(0)
</span><span class="cx">     , m_averageBufferRate(0)
</span><ins>+    , m_pendingRemoveStart(MediaTime::invalidTime())
+    , m_pendingRemoveEnd(MediaTime::invalidTime())
+    , m_removeTimer(this, &amp;SourceBuffer::removeTimerFired)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_private);
</span><span class="cx">     ASSERT(m_source);
</span><span class="lines">@@ -146,15 +149,11 @@
</span><span class="cx"> {
</span><span class="cx">     // Section 3.1 timestampOffset attribute setter steps.
</span><span class="cx">     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#attributes-1
</span><del>-    // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
</del><ins>+    // 1. Let new timestamp offset equal the new value being assigned to this attribute.
+    // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw an
</ins><span class="cx">     //    INVALID_STATE_ERR exception and abort these steps.
</span><del>-    if (isRemoved()) {
-        ec = INVALID_STATE_ERR;
-        return;
-    }
-
</del><span class="cx">     // 3. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
</span><del>-    if (m_updating) {
</del><ins>+    if (isRemoved() || m_updating) {
</ins><span class="cx">         ec = INVALID_STATE_ERR;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -170,7 +169,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 6. Update the attribute to the new value.
</del><ins>+    // FIXME: Add step 6 text when mode attribute is implemented.
+    // 7. Update the attribute to the new value.
</ins><span class="cx">     m_timestampOffset = MediaTime::createWithDouble(offset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -222,7 +222,41 @@
</span><span class="cx">     // FIXME(229408) Add steps 5-6 update appendWindowStart &amp; appendWindowEnd.
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBuffer::remove(double start, double end, ExceptionCode&amp; ec)
+{
+    // Section 3.2 remove() method steps.
+    // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
+    // 2. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps.
+    if (start &lt; 0 || (m_source &amp;&amp; (std::isnan(m_source-&gt;duration()) || start &gt; m_source-&gt;duration())) || end &lt;= start) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
</ins><span class="cx"> 
</span><ins>+    // 3. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
+    //    InvalidStateError exception and abort these steps.
+    // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
+    if (isRemoved() || m_updating) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+
+    // 5. If the readyState attribute of the parent media source is in the &quot;ended&quot; state then run the following steps:
+    // 5.1. Set the readyState attribute of the parent media source to &quot;open&quot;
+    // 5.2. Queue a task to fire a simple event named sourceopen at the parent media source .
+    m_source-&gt;openIfInEndedState();
+
+    // 6. Set the updating attribute to true.
+    m_updating = true;
+
+    // 7. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
+    scheduleEvent(eventNames().updatestartEvent);
+
+    // 8. Return control to the caller and run the rest of the steps asynchronously.
+    m_pendingRemoveStart = MediaTime::createWithDouble(start);
+    m_pendingRemoveEnd = MediaTime::createWithDouble(end);
+    m_removeTimer.startOneShot(0);
+}
+
</ins><span class="cx"> void SourceBuffer::abortIfUpdating()
</span><span class="cx"> {
</span><span class="cx">     // Section 3.2 abort() method step 3 substeps.
</span><span class="lines">@@ -235,6 +269,10 @@
</span><span class="cx">     m_appendBufferTimer.stop();
</span><span class="cx">     m_pendingAppendData.clear();
</span><span class="cx"> 
</span><ins>+    m_removeTimer.stop();
+    m_pendingRemoveStart = MediaTime::invalidTime();
+    m_pendingRemoveEnd = MediaTime::invalidTime();
+
</ins><span class="cx">     // 3.2. Set the updating attribute to false.
</span><span class="cx">     m_updating = false;
</span><span class="cx"> 
</span><span class="lines">@@ -250,6 +288,8 @@
</span><span class="cx">     if (isRemoved())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    abortIfUpdating();
+
</ins><span class="cx">     m_private-&gt;removedFromMediaSource();
</span><span class="cx">     m_source = 0;
</span><span class="cx">     m_asyncEventQueue.close();
</span><span class="lines">@@ -346,6 +386,7 @@
</span><span class="cx"> void SourceBuffer::stop()
</span><span class="cx"> {
</span><span class="cx">     m_appendBufferTimer.stop();
</span><ins>+    m_removeTimer.stop();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SourceBuffer::isRemoved() const
</span><span class="lines">@@ -470,6 +511,79 @@
</span><span class="cx">         provideMediaData(iter-&gt;value, iter-&gt;key);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBuffer::removeCodedFrames(const MediaTime&amp; start, const MediaTime&amp; end)
+{
+    // 3.5.9 Coded Frame Removal Algorithm
+    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebuffer-coded-frame-removal
+
+    // 1. Let start be the starting presentation timestamp for the removal range.
+    MediaTime durationMediaTime = MediaTime::createWithDouble(m_source-&gt;duration());
+    MediaTime currentMediaTime = MediaTime::createWithDouble(m_source-&gt;currentTime());
+
+    // 2. Let end be the end presentation timestamp for the removal range.
+    // 3. For each track buffer in this source buffer, run the following steps:
+    for (auto iter : m_trackBufferMap) {
+        TrackBuffer&amp; trackBuffer = iter.value;
+        // 3.1. Let remove end timestamp be the current value of duration
+        SampleMap::iterator removeEnd = trackBuffer.samples.presentationEnd();
+
+        // 3.2 If this track buffer has a random access point timestamp that is greater than or equal to end, then update
+        // remove end timestamp to that random access point timestamp.
+        SampleMap::iterator nextRandomAccessPoint = trackBuffer.samples.findSyncSampleAfterPresentationTime(end);
+        if (nextRandomAccessPoint-&gt;first &gt;= end)
+            removeEnd = trackBuffer.samples.findSampleContainingPresentationTime(nextRandomAccessPoint-&gt;first);
+
+        // 3.3 Remove all media data, from this track buffer, that contain starting timestamps greater than or equal to
+        // start and less than the remove end timestamp.
+        SampleMap::iterator removeStart = trackBuffer.samples.findSampleAfterPresentationTime(start);
+        SampleMap::MapType erasedSamples(removeStart, removeEnd);
+        RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
+        MediaTime microsecond(1, 1000000);
+        for (auto erasedIt : erasedSamples) {
+            trackBuffer.samples.removeSample(erasedIt.second.get());
+            double startTime = erasedIt.first.toDouble();
+            double endTime = ((erasedIt.first + erasedIt.second-&gt;duration()) + microsecond).toDouble();
+            erasedRanges-&gt;add(startTime, endTime);
+        }
+
+        erasedRanges-&gt;invert();
+        m_buffered-&gt;intersectWith(*erasedRanges);
+
+        // 3.4 If this object is in activeSourceBuffers, the current playback position is greater than or equal to start
+        // and less than the remove end timestamp, and HTMLMediaElement.readyState is greater than HAVE_METADATA, then set
+        // the HTMLMediaElement.readyState attribute to HAVE_METADATA and stall playback.
+        if (m_active &amp;&amp; currentMediaTime &gt;= start &amp;&amp; currentMediaTime &lt; end &amp;&amp; m_private-&gt;readyState() &gt; MediaPlayer::HaveMetadata)
+            m_private-&gt;setReadyState(MediaPlayer::HaveMetadata);
+    }
+
+    // 4. If buffer full flag equals true and this object is ready to accept more bytes, then set the buffer full flag to false.
+    // No-op
+}
+
+void SourceBuffer::removeTimerFired(Timer&lt;SourceBuffer&gt;*)
+{
+    ASSERT(m_updating);
+    ASSERT(m_pendingRemoveStart.isValid());
+    ASSERT(m_pendingRemoveStart &lt; m_pendingRemoveEnd);
+
+    // Section 3.2 remove() method steps
+    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
+
+    // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
+    removeCodedFrames(m_pendingRemoveStart, m_pendingRemoveEnd);
+
+    // 10. Set the updating attribute to false.
+    m_updating = false;
+    m_pendingRemoveStart = MediaTime::invalidTime();
+    m_pendingRemoveEnd = MediaTime::invalidTime();
+
+    // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
+    scheduleEvent(eventNames().updateEvent);
+
+    // 12. Queue a task to fire a simple event named updateend at this SourceBuffer object.
+    scheduleEvent(eventNames().updateendEvent);
+}
+
</ins><span class="cx"> const AtomicString&amp; SourceBuffer::decodeError()
</span><span class="cx"> {
</span><span class="cx">     static NeverDestroyed&lt;AtomicString&gt; decode(&quot;decode&quot;, AtomicString::ConstructFromLiteral);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (166422 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-03-28 19:57:34 UTC (rev 166422)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx">     void appendBuffer(PassRefPtr&lt;ArrayBuffer&gt; data, ExceptionCode&amp;);
</span><span class="cx">     void appendBuffer(PassRefPtr&lt;ArrayBufferView&gt; data, ExceptionCode&amp;);
</span><span class="cx">     void abort(ExceptionCode&amp;);
</span><ins>+    void remove(double start, double end, ExceptionCode&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void abortIfUpdating();
</span><span class="cx">     void removedFromMediaSource();
</span><span class="lines">@@ -152,6 +153,9 @@
</span><span class="cx"> 
</span><span class="cx">     void monitorBufferingRate();
</span><span class="cx"> 
</span><ins>+    void removeTimerFired(Timer&lt;SourceBuffer&gt;*);
+    void removeCodedFrames(const MediaTime&amp; start, const MediaTime&amp; end);
+
</ins><span class="cx">     RefPtr&lt;SourceBufferPrivate&gt; m_private;
</span><span class="cx">     MediaSource* m_source;
</span><span class="cx">     GenericEventQueue m_asyncEventQueue;
</span><span class="lines">@@ -183,6 +187,10 @@
</span><span class="cx">     double m_timeOfBufferingMonitor;
</span><span class="cx">     double m_bufferedSinceLastMonitor;
</span><span class="cx">     double m_averageBufferRate;
</span><ins>+
+    MediaTime m_pendingRemoveStart;
+    MediaTime m_pendingRemoveEnd;
+    Timer&lt;SourceBuffer&gt; m_removeTimer;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.idl (166422 => 166423)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.idl        2014-03-28 19:57:34 UTC (rev 166422)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.idl        2014-03-28 20:08:51 UTC (rev 166423)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Abort the current segment append sequence.
</span><span class="cx">     [RaisesException] void abort();
</span><ins>+    [RaisesException] void remove(double start, double end);
</ins><span class="cx">     
</span><span class="cx">     // Track support
</span><span class="cx">     [Conditional=VIDEO_TRACK] readonly attribute AudioTrackList audioTracks;
</span></span></pre>
</div>
</div>

</body>
</html>