<!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>[159519] 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/159519">159519</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2013-11-19 13:39:43 -0800 (Tue, 19 Nov 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE] Support fastSeek() in MediaSource.
https://bugs.webkit.org/show_bug.cgi?id=124422

Reviewed by Eric Carlson.

Source/WebCore:

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

* Modules/mediasource/MediaSource.cpp:
* Modules/mediasource/MediaSource.h:

Add support for &quot;seek to the next fastest time&quot; in MediaSource by
returning the time of the nearest Sync sample.

Move the data structure logic out of SourceBuffer and into it's own
class:
* Modules/mediasource/SampleMap.cpp: Added.
(WebCore::SampleIsLessThanMediaTimeComparator::operator()):
(WebCore::SampleIsGreaterThanMediaTimeComparator::operator()):
(WebCore::SampleIsRandomAccess::operator()):
(WebCore::SamplePresentationTimeIsWithinRangeComparator::operator()):
(WebCore::SampleMap::addSample):
(WebCore::SampleMap::removeSample):
(WebCore::SampleMap::findSampleContainingPresentationTime):
(WebCore::SampleMap::findSampleAfterPresentationTime):
(WebCore::SampleMap::findSampleWithDecodeTime):
(WebCore::SampleMap::reverseFindSampleContainingPresentationTime):
(WebCore::SampleMap::reverseFindSampleBeforePresentationTime):
(WebCore::SampleMap::reverseFindSampleWithDecodeTime):
(WebCore::SampleMap::findSyncSamplePriorToPresentationTime):
(WebCore::SampleMap::findSyncSamplePriorToDecodeIterator):
(WebCore::SampleMap::findSyncSampleAfterPresentationTime):
(WebCore::SampleMap::findSyncSampleAfterDecodeIterator):
(WebCore::SampleMap::findSamplesBetweenPresentationTimes):
(WebCore::SampleMap::findDependentSamples):
* Modules/mediasource/SampleMap.h: Added.
(WebCore::SampleMap::presentationBegin):
(WebCore::SampleMap::presentationEnd):
(WebCore::SampleMap::decodeBegin):
(WebCore::SampleMap::decodeEnd):
(WebCore::SampleMap::reversePresentationBegin):
(WebCore::SampleMap::reversePresentationEnd):
(WebCore::SampleMap::reverseDecodeBegin):
(WebCore::SampleMap::reverseDecodeEnd):

Add logic to find and return the time of the next &amp; previous sync
sample, within the threshold provided:
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::TrackBuffer::TrackBuffer):
(WebCore::SourceBuffer::sourceBufferPrivateSeekToTime):
(WebCore::SourceBuffer::sourceBufferPrivateFastSeekTimeForMediaTime):
(WebCore::SourceBuffer::appendBufferTimerFired):
(WebCore::SourceBuffer::setActive):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
(WebCore::SourceBuffer::sourceBufferPrivateDidBecomeReadyForMoreSamples):
(WebCore::SourceBuffer::provideMediaData):
* Modules/mediasource/SourceBuffer.h:
* platform/graphics/SourceBufferPrivate.h:
(WebCore::SourceBufferPrivate::setActive):
* platform/graphics/SourceBufferPrivateClient.h:
(WebCore::SourceBufferPrivateClient::sourceBufferPrivateFastSeekTimeForMediaTime):
(WebCore::SourceBufferPrivateClient::sourceBufferPrivateSeekToTime):

Add new files to the project:
* WebCore.xcodeproj/project.pbxproj:

Drive-by fixes in HTMLMediaElement:
* html/HTMLMediaSource.h:
* html/HTMLMediaElement.cpp:
(HTMLMediaElement::finishSeek): Cause the MediaSource to check the ready state of all its buffers.
(HTMLMediaElement::selectNextSourceChild): Pass in whether the source element has a MediaSource URL.

Implement the seekWithTolerance behavior in MockMediaPlayerMediaSource:
* platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
(WebCore::MockMediaPlayerMediaSource::maxTimeSeekableDouble):
(WebCore::MockMediaPlayerMediaSource::currentTimeDouble):
(WebCore::MockMediaPlayerMediaSource::seekWithTolerance):
(WebCore::MockMediaPlayerMediaSource::advanceCurrentTime):
* platform/mock/mediasource/MockMediaPlayerMediaSource.h:
* platform/mock/mediasource/MockMediaSourcePrivate.cpp:
(WebCore::MockMediaSourcePrivate::seekToTime):
* platform/mock/mediasource/MockMediaSourcePrivate.h:
* platform/mock/mediasource/MockSourceBufferPrivate.cpp:
(WebCore::MockMediaSample::flags):
(WebCore::MockSourceBufferPrivate::setActive):
(WebCore::MockSourceBufferPrivate::fastSeekTimeForMediaTime):
(WebCore::MockSourceBufferPrivate::seekToTime):
* platform/mock/mediasource/MockSourceBufferPrivate.h:

LayoutTests:

* media/media-source/media-source-fastseek-expected.txt: Added.
* media/media-source/media-source-fastseek.html: Added.
* media/media-source/mock-media-source.js:
(var):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemockmediasourcejs">trunk/LayoutTests/media/media-source/mock-media-source.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreGNUmakefilelistam">trunk/Source/WebCore/GNUmakefile.list.am</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="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaSourceh">trunk/Source/WebCore/html/HTMLMediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformMediaSampleh">trunk/Source/WebCore/platform/MediaSample.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsSourceBufferPrivateh">trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsSourceBufferPrivateClienth">trunk/Source/WebCore/platform/graphics/SourceBufferPrivateClient.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourcecpp">trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourceh">trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivatecpp">trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivateh">trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp">trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh">trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcefastseekexpectedtxt">trunk/LayoutTests/media/media-source/media-source-fastseek-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcefastseekhtml">trunk/LayoutTests/media/media-source/media-source-fastseek.html</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSampleMapcpp">trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSampleMaph">trunk/Source/WebCore/Modules/mediasource/SampleMap.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/LayoutTests/ChangeLog        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2013-11-15  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Support fastSeek() in MediaSource.
+        https://bugs.webkit.org/show_bug.cgi?id=124422
+
+        Reviewed by Eric Carlson.
+
+        * media/media-source/media-source-fastseek-expected.txt: Added.
+        * media/media-source/media-source-fastseek.html: Added.
+        * media/media-source/mock-media-source.js:
+        (var):
+
</ins><span class="cx"> 2013-11-19  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         fast/forms/form-associated-element-crash.html often times out on Mavericks WK1
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcefastseekexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-fastseek-expected.txt (0 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-fastseek-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-fastseek-expected.txt        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+
+EXPECTED (source.readyState == 'closed') OK
+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(source.duration = 8)
+RUN(source.endOfStream())
+RUN(video.currentTime = 1)
+EVENT(seeked)
+EXPECTED (video.currentTime.toFixed(1) == '1') OK
+RUN(video.fastSeek(2))
+EVENT(seeked)
+EXPECTED (video.currentTime.toFixed(1) == '4') OK
+RUN(video.currentTime = 3)
+EVENT(seeked)
+EXPECTED (video.currentTime.toFixed(1) == '3') OK
+RUN(video.fastSeek(2))
+EVENT(seeked)
+EXPECTED (video.currentTime.toFixed(1) == '0') OK
+END OF TEST
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcefastseekhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-fastseek.html (0 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-fastseek.html                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-fastseek.html        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -0,0 +1,87 @@
</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;
+    var samples;
+
+    if (window.internals)
+        internals.initializeMockMediaSource();
+
+    function runTest() {
+        findMediaElement();
+
+        source = new MediaSource();
+        testExpected('source.readyState', 'closed');
+
+        waitForEventOn(source, 'sourceopen', sourceOpen);
+        var videoSource = document.createElement('source');
+        videoSource.type = 'video/mock; codecs=mock';
+        videoSource.src = URL.createObjectURL(source);
+        video.appendChild(videoSource);
+    }
+
+    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', play, false, true);
+        run('sourceBuffer.appendBuffer(samples)');
+    }
+
+    function play() {
+        waitForEvent('ended', endTest);
+        run('source.duration = 8');
+        run('source.endOfStream()');
+        waitForEventOnce('seeked', seeked1);
+        run('video.currentTime = 1');
+    }
+
+    function seeked1() {
+        testExpected('video.currentTime.toFixed(1)', 1);
+        waitForEventOnce('seeked', seeked2);
+        run('video.fastSeek(2)');
+    }
+
+    function seeked2() {
+        testExpected('video.currentTime.toFixed(1)', 4);
+        waitForEventOnce('seeked', seeked3);
+        run('video.currentTime = 3');
+    }
+
+    function seeked3() {
+        testExpected('video.currentTime.toFixed(1)', 3);
+        waitForEventOnce('seeked', seeked4);
+        run('video.fastSeek(2)');
+    }
+
+    function seeked4() {
+        testExpected('video.currentTime.toFixed(1)', 0);
+        endTest();
+    }
+    
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;video&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemockmediasourcejs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/media-source/mock-media-source.js (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/mock-media-source.js        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/LayoutTests/media/media-source/mock-media-source.js        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -8,6 +8,11 @@
</span><span class="cx">     return string.split(&quot;&quot;).map(function(c){ return c.charCodeAt(0); });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+var SAMPLE_FLAG = {
+    NONE: 0,
+    SYNC: 1 &lt;&lt; 0,
+};
+
</ins><span class="cx"> function makeASample(presentationTime, decodeTime, duration, trackID, flags) {
</span><span class="cx">     var byteLength = 29;
</span><span class="cx">     var buffer = new ArrayBuffer(byteLength);
</span><span class="lines">@@ -28,6 +33,22 @@
</span><span class="cx">     return buffer;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function concatenateSamples(samples) {
+    var byteLength = 0;
+    samples.forEach(function(sample) { byteLength += sample.byteLength; });
+    var buffer = new ArrayBuffer(byteLength);
+
+    var offset = 0;
+    samples.forEach(function(sample){
+        var sourceArray = new Uint8Array(sample);
+        var destArray = new Uint8Array(buffer, offset, sourceArray.byteLength);
+        destArray.set(sourceArray);
+        offset += sourceArray.byteLength;
+    });
+
+    return buffer;
+}
+
</ins><span class="cx"> function makeATrack(trackID, codec, flags) {
</span><span class="cx">     var byteLength = 17;
</span><span class="cx">     var buffer = new ArrayBuffer(byteLength);
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/ChangeLog        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -1,3 +1,93 @@
</span><ins>+2013-11-15  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Support fastSeek() in MediaSource.
+        https://bugs.webkit.org/show_bug.cgi?id=124422
+
+        Reviewed by Eric Carlson.
+
+        Test: media/media-source/media-source-fastseek.html
+
+        * Modules/mediasource/MediaSource.cpp:
+        * Modules/mediasource/MediaSource.h:
+
+        Add support for &quot;seek to the next fastest time&quot; in MediaSource by
+        returning the time of the nearest Sync sample.
+
+        Move the data structure logic out of SourceBuffer and into it's own
+        class:
+        * Modules/mediasource/SampleMap.cpp: Added.
+        (WebCore::SampleIsLessThanMediaTimeComparator::operator()):
+        (WebCore::SampleIsGreaterThanMediaTimeComparator::operator()):
+        (WebCore::SampleIsRandomAccess::operator()):
+        (WebCore::SamplePresentationTimeIsWithinRangeComparator::operator()):
+        (WebCore::SampleMap::addSample):
+        (WebCore::SampleMap::removeSample):
+        (WebCore::SampleMap::findSampleContainingPresentationTime):
+        (WebCore::SampleMap::findSampleAfterPresentationTime):
+        (WebCore::SampleMap::findSampleWithDecodeTime):
+        (WebCore::SampleMap::reverseFindSampleContainingPresentationTime):
+        (WebCore::SampleMap::reverseFindSampleBeforePresentationTime):
+        (WebCore::SampleMap::reverseFindSampleWithDecodeTime):
+        (WebCore::SampleMap::findSyncSamplePriorToPresentationTime):
+        (WebCore::SampleMap::findSyncSamplePriorToDecodeIterator):
+        (WebCore::SampleMap::findSyncSampleAfterPresentationTime):
+        (WebCore::SampleMap::findSyncSampleAfterDecodeIterator):
+        (WebCore::SampleMap::findSamplesBetweenPresentationTimes):
+        (WebCore::SampleMap::findDependentSamples):
+        * Modules/mediasource/SampleMap.h: Added.
+        (WebCore::SampleMap::presentationBegin):
+        (WebCore::SampleMap::presentationEnd):
+        (WebCore::SampleMap::decodeBegin):
+        (WebCore::SampleMap::decodeEnd):
+        (WebCore::SampleMap::reversePresentationBegin):
+        (WebCore::SampleMap::reversePresentationEnd):
+        (WebCore::SampleMap::reverseDecodeBegin):
+        (WebCore::SampleMap::reverseDecodeEnd):
+
+        Add logic to find and return the time of the next &amp; previous sync
+        sample, within the threshold provided:
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::TrackBuffer::TrackBuffer):
+        (WebCore::SourceBuffer::sourceBufferPrivateSeekToTime):
+        (WebCore::SourceBuffer::sourceBufferPrivateFastSeekTimeForMediaTime):
+        (WebCore::SourceBuffer::appendBufferTimerFired):
+        (WebCore::SourceBuffer::setActive):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidBecomeReadyForMoreSamples):
+        (WebCore::SourceBuffer::provideMediaData):
+        * Modules/mediasource/SourceBuffer.h:
+        * platform/graphics/SourceBufferPrivate.h:
+        (WebCore::SourceBufferPrivate::setActive):
+        * platform/graphics/SourceBufferPrivateClient.h:
+        (WebCore::SourceBufferPrivateClient::sourceBufferPrivateFastSeekTimeForMediaTime):
+        (WebCore::SourceBufferPrivateClient::sourceBufferPrivateSeekToTime):
+
+        Add new files to the project:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        Drive-by fixes in HTMLMediaElement:
+        * html/HTMLMediaSource.h:
+        * html/HTMLMediaElement.cpp:
+        (HTMLMediaElement::finishSeek): Cause the MediaSource to check the ready state of all its buffers.
+        (HTMLMediaElement::selectNextSourceChild): Pass in whether the source element has a MediaSource URL.
+
+        Implement the seekWithTolerance behavior in MockMediaPlayerMediaSource:
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
+        (WebCore::MockMediaPlayerMediaSource::maxTimeSeekableDouble):
+        (WebCore::MockMediaPlayerMediaSource::currentTimeDouble):
+        (WebCore::MockMediaPlayerMediaSource::seekWithTolerance):
+        (WebCore::MockMediaPlayerMediaSource::advanceCurrentTime):
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.h:
+        * platform/mock/mediasource/MockMediaSourcePrivate.cpp:
+        (WebCore::MockMediaSourcePrivate::seekToTime):
+        * platform/mock/mediasource/MockMediaSourcePrivate.h:
+        * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+        (WebCore::MockMediaSample::flags):
+        (WebCore::MockSourceBufferPrivate::setActive):
+        (WebCore::MockSourceBufferPrivate::fastSeekTimeForMediaTime):
+        (WebCore::MockSourceBufferPrivate::seekToTime):
+        * platform/mock/mediasource/MockSourceBufferPrivate.h:
+
</ins><span class="cx"> 2013-11-19  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Mac] 10X slower than Chrome when drawing a video into a canvas
</span></span></pre></div>
<a id="trunkSourceWebCoreGNUmakefilelistam"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/GNUmakefile.list.am (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/GNUmakefile.list.am        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/GNUmakefile.list.am        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -1879,6 +1879,8 @@
</span><span class="cx">         Source/WebCore/Modules/mediasource/SourceBufferList.h \
</span><span class="cx">         Source/WebCore/Modules/mediasource/DOMURLMediaSource.cpp \
</span><span class="cx">         Source/WebCore/Modules/mediasource/DOMURLMediaSource.h \
</span><ins>+        Source/WebCore/Modules/mediasource/SampleMap.cpp \
+        Source/WebCore/Modules/mediasource/SampleMap.h \
</ins><span class="cx">         Source/WebCore/Modules/mediastream/AllAudioCapabilities.h \
</span><span class="cx">         Source/WebCore/Modules/mediastream/AllVideoCapabilities.h \
</span><span class="cx">         Source/WebCore/Modules/mediastream/AudioStreamTrack.cpp \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -452,8 +452,6 @@
</span><span class="cx">     // 4. Abort these steps.
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/MediaSource.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx"> 
</span><span class="cx">     void sourceBufferDidChangeAcitveState(SourceBuffer*, bool);
</span><span class="cx"> 
</span><del>-    void monitorSourceBuffers();
</del><ins>+    virtual void monitorSourceBuffers() OVERRIDE;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     explicit MediaSource(ScriptExecutionContext&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSampleMapcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp (0 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -0,0 +1,190 @@
</span><ins>+/*
+ * Copyright (C) 2013 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 &quot;config.h&quot;
+#include &quot;SampleMap.h&quot;
+
+#if ENABLE(MEDIA_SOURCE)
+
+#include &quot;MediaSample.h&quot;
+
+namespace WebCore {
+
+class SampleIsLessThanMediaTimeComparator {
+public:
+    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value, MediaTime time)
+    {
+        MediaTime presentationEndTime = value.second-&gt;presentationTime() + value.second-&gt;duration();
+        return presentationEndTime &lt;= time;
+    }
+    bool operator()(MediaTime time, std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
+    {
+        MediaTime presentationStartTime = value.second-&gt;presentationTime();
+        return time &lt; presentationStartTime;
+    }
+};
+
+class SampleIsGreaterThanMediaTimeComparator {
+public:
+    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value, MediaTime time)
+    {
+        MediaTime presentationStartTime = value.second-&gt;presentationTime();
+        return presentationStartTime &gt; time;
+    }
+    bool operator()(MediaTime time, std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
+    {
+        MediaTime presentationEndTime = value.second-&gt;presentationTime() + value.second-&gt;duration();
+        return time &gt;= presentationEndTime;
+    }
+};
+
+class SampleIsRandomAccess {
+public:
+    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
+    {
+        return value.second-&gt;flags() == MediaSample::IsSync;
+    }
+};
+
+class SamplePresentationTimeIsWithinRangeComparator {
+public:
+    bool operator()(std::pair&lt;MediaTime, MediaTime&gt; range, std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
+    {
+        return range.second &lt; value.first;
+    }
+    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value, std::pair&lt;MediaTime, MediaTime&gt; range)
+    {
+        return value.first &lt; range.first;
+    }
+};
+
+void SampleMap::addSample(PassRefPtr&lt;MediaSample&gt; prpSample)
+{
+    RefPtr&lt;MediaSample&gt; sample = prpSample;
+    ASSERT(sample);
+    m_presentationSamples.insert(MapType::value_type(sample-&gt;presentationTime(), sample));
+    m_decodeSamples.insert(MapType::value_type(sample-&gt;decodeTime(), sample));
+}
+
+void SampleMap::removeSample(MediaSample* sample)
+{
+    ASSERT(sample);
+    m_presentationSamples.erase(sample-&gt;presentationTime());
+    m_decodeSamples.erase(sample-&gt;decodeTime());
+}
+
+SampleMap::iterator SampleMap::findSampleContainingPresentationTime(const MediaTime&amp; time)
+{
+    return std::equal_range(presentationBegin(), presentationEnd(), time, SampleIsLessThanMediaTimeComparator()).first;
+}
+
+SampleMap::iterator SampleMap::findSampleAfterPresentationTime(const MediaTime&amp; time)
+{
+    return std::lower_bound(presentationBegin(), presentationEnd(), time, SampleIsLessThanMediaTimeComparator());
+}
+
+SampleMap::iterator SampleMap::findSampleWithDecodeTime(const MediaTime&amp; time)
+{
+    return m_decodeSamples.find(time);
+}
+
+SampleMap::reverse_iterator SampleMap::reverseFindSampleContainingPresentationTime(const MediaTime&amp; time)
+{
+    return std::equal_range(reversePresentationBegin(), reversePresentationEnd(), time, SampleIsGreaterThanMediaTimeComparator()).first;
+}
+
+SampleMap::reverse_iterator SampleMap::reverseFindSampleBeforePresentationTime(const MediaTime&amp; time)
+{
+    return std::lower_bound(reversePresentationBegin(), reversePresentationEnd(), time, SampleIsGreaterThanMediaTimeComparator());
+}
+
+SampleMap::reverse_iterator SampleMap::reverseFindSampleWithDecodeTime(const MediaTime&amp; time)
+{
+    SampleMap::iterator found = findSampleWithDecodeTime(time);
+    if (found == decodeEnd())
+        return reverseDecodeEnd();
+    return --reverse_iterator(found);
+}
+
+SampleMap::reverse_iterator SampleMap::findSyncSamplePriorToPresentationTime(const MediaTime&amp; time, const MediaTime&amp; threshold)
+{
+    reverse_iterator reverseCurrentSamplePTS = reverseFindSampleBeforePresentationTime(time);
+    if (reverseCurrentSamplePTS == reversePresentationEnd())
+        return reverseDecodeEnd();
+
+    reverse_iterator reverseCurrentSampleDTS = reverseFindSampleWithDecodeTime(reverseCurrentSamplePTS-&gt;second-&gt;decodeTime());
+
+    reverse_iterator foundSample = findSyncSamplePriorToDecodeIterator(reverseCurrentSampleDTS);
+    if (foundSample == reverseDecodeEnd())
+        return reverseDecodeEnd();
+    if (foundSample-&gt;second-&gt;presentationTime() &lt; time - threshold)
+        return reverseDecodeEnd();
+    return foundSample;
+}
+
+SampleMap::reverse_iterator SampleMap::findSyncSamplePriorToDecodeIterator(reverse_iterator iterator)
+{
+    return std::find_if(iterator, reverseDecodeEnd(), SampleIsRandomAccess());
+}
+
+SampleMap::iterator SampleMap::findSyncSampleAfterPresentationTime(const MediaTime&amp; time, const MediaTime&amp; threshold)
+{
+    iterator currentSamplePTS = findSampleAfterPresentationTime(time);
+    if (currentSamplePTS == presentationEnd())
+        return decodeEnd();
+
+    iterator currentSampleDTS = findSampleWithDecodeTime(currentSamplePTS-&gt;second-&gt;decodeTime());
+    
+    MediaTime upperBound = time + threshold;
+    iterator foundSample = std::find_if(currentSampleDTS, decodeEnd(), SampleIsRandomAccess());
+    if (foundSample == decodeEnd())
+        return decodeEnd();
+    if (foundSample-&gt;second-&gt;presentationTime() &gt; upperBound)
+        return decodeEnd();
+    return foundSample;
+}
+
+SampleMap::iterator SampleMap::findSyncSampleAfterDecodeIterator(iterator currentSampleDTS)
+{
+    return std::find_if(currentSampleDTS, decodeEnd(), SampleIsRandomAccess());
+}
+
+SampleMap::iterator_range SampleMap::findSamplesBetweenPresentationTimes(const MediaTime&amp; begin, const MediaTime&amp; end)
+{
+    std::pair&lt;MediaTime, MediaTime&gt; range(begin, end);
+    return std::equal_range(presentationBegin(), presentationEnd(), range, SamplePresentationTimeIsWithinRangeComparator());
+}
+
+SampleMap::reverse_iterator_range SampleMap::findDependentSamples(MediaSample* sample)
+{
+    ASSERT(sample);
+    reverse_iterator currentDecodeIter = reverseFindSampleWithDecodeTime(sample-&gt;decodeTime());
+    reverse_iterator nextSyncSample = findSyncSamplePriorToDecodeIterator(currentDecodeIter);
+    return reverse_iterator_range(currentDecodeIter, nextSyncSample);
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSampleMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediasource/SampleMap.h (0 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SampleMap.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2013 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#ifndef SampleMap_h
+#define SampleMap_h
+
+#if ENABLE(MEDIA_SOURCE)
+
+#include &lt;map&gt;
+#include &lt;wtf/MediaTime.h&gt;
+#include &lt;wtf/RefPtr.h&gt;
+
+namespace WebCore {
+
+class MediaSample;
+
+class SampleMap {
+public:
+    typedef std::map&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; MapType;
+    typedef MapType::iterator iterator;
+    typedef MapType::reverse_iterator reverse_iterator;
+    typedef std::pair&lt;iterator, iterator&gt; iterator_range;
+    typedef std::pair&lt;reverse_iterator, reverse_iterator&gt; reverse_iterator_range;
+
+    void addSample(PassRefPtr&lt;MediaSample&gt;);
+    void removeSample(MediaSample*);
+
+    iterator presentationBegin() { return m_presentationSamples.begin(); }
+    iterator presentationEnd() { return m_presentationSamples.end(); }
+    iterator decodeBegin() { return m_decodeSamples.begin(); }
+    iterator decodeEnd() { return m_decodeSamples.end(); }
+    reverse_iterator reversePresentationBegin() { return m_presentationSamples.rbegin(); }
+    reverse_iterator reversePresentationEnd() { return m_presentationSamples.rend(); }
+    reverse_iterator reverseDecodeBegin() { return m_decodeSamples.rbegin(); }
+    reverse_iterator reverseDecodeEnd() { return m_decodeSamples.rend(); }
+
+    iterator findSampleContainingPresentationTime(const MediaTime&amp;);
+    iterator findSampleAfterPresentationTime(const MediaTime&amp;);
+    iterator findSampleWithDecodeTime(const MediaTime&amp;);
+    reverse_iterator reverseFindSampleContainingPresentationTime(const MediaTime&amp;);
+    reverse_iterator reverseFindSampleBeforePresentationTime(const MediaTime&amp;);
+    reverse_iterator reverseFindSampleWithDecodeTime(const MediaTime&amp;);
+    reverse_iterator findSyncSamplePriorToPresentationTime(const MediaTime&amp;, const MediaTime&amp; threshold = MediaTime::positiveInfiniteTime());
+    reverse_iterator findSyncSamplePriorToDecodeIterator(reverse_iterator);
+    iterator findSyncSampleAfterPresentationTime(const MediaTime&amp;, const MediaTime&amp; threshold = MediaTime::positiveInfiniteTime());
+    iterator findSyncSampleAfterDecodeIterator(iterator);
+
+    iterator_range findSamplesBetweenPresentationTimes(const MediaTime&amp;, const MediaTime&amp;);
+    reverse_iterator_range findDependentSamples(MediaSample*);
+    
+private:
+    MapType m_presentationSamples;
+    MapType m_decodeSamples;
+};
+
+}
+
+#endif
+
+#endif // SampleMap_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> #include &quot;MediaDescription.h&quot;
</span><span class="cx"> #include &quot;MediaSample.h&quot;
</span><span class="cx"> #include &quot;MediaSource.h&quot;
</span><ins>+#include &quot;SampleMap.h&quot;
</ins><span class="cx"> #include &quot;SourceBufferPrivate.h&quot;
</span><span class="cx"> #include &quot;TextTrackList.h&quot;
</span><span class="cx"> #include &quot;TimeRanges.h&quot;
</span><span class="lines">@@ -58,9 +59,9 @@
</span><span class="cx">     MediaTime highestPresentationTimestamp;
</span><span class="cx">     MediaTime lastEnqueuedPresentationTime;
</span><span class="cx">     bool needRandomAccessFlag;
</span><del>-    typedef std::multimap&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; SampleMap;
</del><ins>+    bool enabled;
</ins><span class="cx">     SampleMap samples;
</span><del>-    SampleMap decodeQueue;
</del><ins>+    SampleMap::MapType decodeQueue;
</ins><span class="cx">     RefPtr&lt;MediaDescription&gt; description;
</span><span class="cx"> 
</span><span class="cx">     TrackBuffer()
</span><span class="lines">@@ -69,6 +70,7 @@
</span><span class="cx">         , highestPresentationTimestamp(MediaTime::invalidTime())
</span><span class="cx">         , lastEnqueuedPresentationTime(MediaTime::invalidTime())
</span><span class="cx">         , needRandomAccessFlag(false)
</span><ins>+        , enabled(false)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="lines">@@ -244,6 +246,89 @@
</span><span class="cx">     m_asyncEventQueue.close();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBuffer::sourceBufferPrivateSeekToTime(SourceBufferPrivate*, const MediaTime&amp; time)
+{
+    LOG(Media, &quot;SourceBuffer::sourceBufferPrivateSeekToTime(%p)&quot;, this);
+
+    for (auto trackBufferIterator = m_trackBufferMap.begin(); trackBufferIterator != m_trackBufferMap.end(); ++trackBufferIterator) {
+        TrackBuffer&amp; trackBuffer = trackBufferIterator-&gt;value;
+        AtomicString trackID = trackBufferIterator-&gt;key;
+
+        // Find the sample which contains the current presentation time.
+        auto currentSamplePTSIterator = trackBuffer.samples.findSampleContainingPresentationTime(time);
+
+        if (currentSamplePTSIterator == trackBuffer.samples.presentationEnd()) {
+            trackBuffer.decodeQueue.clear();
+            m_private-&gt;flushAndEnqueueNonDisplayingSamples(Vector&lt;RefPtr&lt;MediaSample&gt;&gt;(), trackID);
+            continue;
+        }
+
+        // Seach backward for the previous sync sample.
+        MediaTime currentSampleDecodeTime = currentSamplePTSIterator-&gt;second-&gt;decodeTime();
+        auto currentSampleDTSIterator = trackBuffer.samples.findSampleWithDecodeTime(currentSampleDecodeTime);
+        ASSERT(currentSampleDTSIterator != trackBuffer.samples.decodeEnd());
+
+        auto reverseCurrentSampleIter = --SampleMap::reverse_iterator(currentSampleDTSIterator);
+        auto reverseLastSyncSampleIter = trackBuffer.samples.findSyncSamplePriorToDecodeIterator(reverseCurrentSampleIter);
+        if (reverseLastSyncSampleIter == trackBuffer.samples.reverseDecodeEnd()) {
+            trackBuffer.decodeQueue.clear();
+            m_private-&gt;flushAndEnqueueNonDisplayingSamples(Vector&lt;RefPtr&lt;MediaSample&gt;&gt;(), trackID);
+            continue;
+        }
+
+        Vector&lt;RefPtr&lt;MediaSample&gt;&gt; nonDisplayingSamples;
+        for (auto iter = reverseLastSyncSampleIter; iter != reverseCurrentSampleIter; --iter)
+            nonDisplayingSamples.append(iter-&gt;second);
+
+        m_private-&gt;flushAndEnqueueNonDisplayingSamples(nonDisplayingSamples, trackID);
+
+        // Fill the decode queue with the remaining samples.
+        trackBuffer.decodeQueue.clear();
+        for (auto iter = currentSampleDTSIterator; iter != trackBuffer.samples.decodeEnd(); ++iter)
+            trackBuffer.decodeQueue.insert(*iter);
+    }
+
+    provideMediaData();   
+}
+
+MediaTime SourceBuffer::sourceBufferPrivateFastSeekTimeForMediaTime(SourceBufferPrivate*, const MediaTime&amp; targetTime, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold)
+{
+    MediaTime seekTime = targetTime;
+    MediaTime lowerBoundTime = targetTime - negativeThreshold;
+    MediaTime upperBoundTime = targetTime + positiveThreshold;
+
+    for (auto trackBufferIterator = m_trackBufferMap.begin(); trackBufferIterator != m_trackBufferMap.end(); ++trackBufferIterator) {
+        TrackBuffer&amp; trackBuffer = trackBufferIterator-&gt;value;
+
+        // Find the sample which contains the target time time.
+        auto futureSyncSampleIterator = trackBuffer.samples.findSyncSampleAfterPresentationTime(targetTime, positiveThreshold);
+        auto pastSyncSampleIterator = trackBuffer.samples.findSyncSamplePriorToPresentationTime(targetTime, negativeThreshold);
+        auto upperBound = trackBuffer.samples.decodeEnd();
+        auto lowerBound = trackBuffer.samples.reverseDecodeEnd();
+
+        if (futureSyncSampleIterator == upperBound &amp;&amp; pastSyncSampleIterator == lowerBound)
+            continue;
+
+        MediaTime futureSeekTime = MediaTime::positiveInfiniteTime();
+        if (futureSyncSampleIterator != upperBound) {
+            RefPtr&lt;MediaSample&gt;&amp; sample = futureSyncSampleIterator-&gt;second;
+            futureSeekTime = sample-&gt;presentationTime();
+        }
+
+        MediaTime pastSeekTime = MediaTime::negativeInfiniteTime();
+        if (pastSyncSampleIterator != lowerBound) {
+            RefPtr&lt;MediaSample&gt;&amp; sample = pastSyncSampleIterator-&gt;second;
+            pastSeekTime = sample-&gt;presentationTime();
+        }
+
+        MediaTime trackSeekTime = abs(targetTime - futureSeekTime) &lt; abs(targetTime - pastSeekTime) ? futureSeekTime : pastSeekTime;
+        if (abs(targetTime - trackSeekTime) &gt; abs(targetTime - seekTime))
+            seekTime = trackSeekTime;
+    }
+
+    return seekTime;
+}
+
</ins><span class="cx"> bool SourceBuffer::hasPendingActivity() const
</span><span class="cx"> {
</span><span class="cx">     return m_source;
</span><span class="lines">@@ -369,6 +454,7 @@
</span><span class="cx">     scheduleEvent(eventNames().updateendEvent);
</span><span class="cx"> 
</span><span class="cx">     m_source-&gt;monitorSourceBuffers();
</span><ins>+    provideMediaData();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const AtomicString&amp; SourceBuffer::decodeError()
</span><span class="lines">@@ -422,6 +508,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     m_active = active;
</span><ins>+    m_private-&gt;setActive(active);
</ins><span class="cx">     m_source-&gt;sourceBufferDidChangeAcitveState(this, active);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -681,44 +768,10 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-class SampleContainsMediaTimeComparator {
-public:
-    bool contains(MediaSample* sample, MediaTime time)
-    {
-        MediaTime presentationStartTime = sample-&gt;presentationTime();
-        MediaTime presentationEndTime = presentationStartTime + sample-&gt;duration();
-        return presentationStartTime &lt;= time &amp;&amp; presentationEndTime &gt; time;
-    }
-    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value, MediaTime time)
-    {
-        MediaTime presentationStartTime = value.second-&gt;presentationTime();
-        MediaTime presentationEndTime = presentationStartTime + value.second-&gt;duration();
-        return presentationStartTime &lt; time &amp;&amp; presentationEndTime &lt;= time;
-    }
-};
</del><ins>+void SourceBuffer::sourceBufferPrivateDidReceiveSample(SourceBufferPrivate*, PassRefPtr&lt;MediaSample&gt; prpSample)
+{
+    RefPtr&lt;MediaSample&gt; sample = prpSample;
</ins><span class="cx"> 
</span><del>-class SamplePresentationTimeIsWithinRangeComparator {
-public:
-    bool operator()(std::pair&lt;MediaTime, MediaTime&gt; range, std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
-    {
-        return range.second &lt; value.first;
-    }
-    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value, std::pair&lt;MediaTime, MediaTime&gt; range)
-    {
-        return value.first &lt; range.first;
-    }
-};
-
-class SampleIsRandomAccess {
-public:
-    bool operator()(std::pair&lt;MediaTime, RefPtr&lt;MediaSample&gt;&gt; value)
-    {
-        return value.second-&gt;flags() == MediaSample::IsSync;
-    }
-};
-
-void SourceBuffer::sourceBufferPrivateDidReceiveSample(SourceBufferPrivate*, PassRefPtr&lt;MediaSample&gt; sample)
-{
</del><span class="cx">     // 3.5.8 Coded Frame Processing
</span><span class="cx">     // When complete coded frames have been parsed by the segment parser loop then the following steps
</span><span class="cx">     // are run:
</span><span class="lines">@@ -816,7 +869,7 @@
</span><span class="cx">         // 1.13 Let spliced timed text frame be an unset variable for holding timed text splice information
</span><span class="cx">         // FIXME: Add support for sample splicing.
</span><span class="cx"> 
</span><del>-        TrackBuffer::SampleMap erasedSamples;
</del><ins>+        SampleMap::MapType erasedSamples;
</ins><span class="cx">         MediaTime microsecond(1, 1000000);
</span><span class="cx"> 
</span><span class="cx">         // 1.14 If last decode timestamp for track buffer is unset and there is a coded frame in
</span><span class="lines">@@ -824,9 +877,8 @@
</span><span class="cx">         // and presentation timestamp is less than this coded frame's presentation timestamp plus
</span><span class="cx">         // its frame duration, then run the following steps:
</span><span class="cx">         if (trackBuffer.lastDecodeTimestamp.isInvalid()) {
</span><del>-            SampleContainsMediaTimeComparator comparator;
-            auto iter = std::lower_bound(trackBuffer.samples.begin(), trackBuffer.samples.end(), presentationTimestamp, comparator);
-            if (iter != trackBuffer.samples.end() &amp;&amp; comparator.contains(iter-&gt;second.get(), presentationTimestamp)) {
</del><ins>+            auto iter = trackBuffer.samples.findSampleContainingPresentationTime(presentationTimestamp);
+            if (iter != trackBuffer.samples.presentationEnd()) {
</ins><span class="cx">                 // 1.14.1 Let overlapped frame be the coded frame in track buffer that matches the condition above.
</span><span class="cx">                 RefPtr&lt;MediaSample&gt; overlappedFrame = iter-&gt;second;
</span><span class="cx"> 
</span><span class="lines">@@ -847,11 +899,8 @@
</span><span class="cx"> 
</span><span class="cx">                     // 1.14.2.3 If the presentation timestamp is less than the remove window timestamp,
</span><span class="cx">                     // then remove overlapped frame and any coded frames that depend on it from track buffer.
</span><del>-                    if (presentationTimestamp &lt; removeWindowTimestamp) {
-                        // NOTE: MockSampleBoxes don't have dependencies
</del><ins>+                    if (presentationTimestamp &lt; removeWindowTimestamp)
</ins><span class="cx">                         erasedSamples.insert(*iter);
</span><del>-                        trackBuffer.samples.erase(iter);
-                    }
</del><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 // If track buffer contains timed text coded frames:
</span><span class="lines">@@ -865,41 +914,52 @@
</span><span class="cx">         if (trackBuffer.highestPresentationTimestamp.isInvalid()) {
</span><span class="cx">             // Remove all coded frames from track buffer that have a presentation timestamp greater than or
</span><span class="cx">             // equal to presentation timestamp and less than frame end timestamp.
</span><del>-            SamplePresentationTimeIsWithinRangeComparator comparator;
-            std::pair&lt;MediaTime, MediaTime&gt; range(presentationTimestamp, frameEndTimestamp);
-            auto iter_pair = std::equal_range(trackBuffer.samples.begin(), trackBuffer.samples.end(), range, comparator);
-            if (iter_pair.first != trackBuffer.samples.end()) {
</del><ins>+            auto iter_pair = trackBuffer.samples.findSamplesBetweenPresentationTimes(presentationTimestamp, frameEndTimestamp);
+            if (iter_pair.first != trackBuffer.samples.presentationEnd())
</ins><span class="cx">                 erasedSamples.insert(iter_pair.first, iter_pair.second);
</span><del>-                trackBuffer.samples.erase(iter_pair.first, iter_pair.second);
-            }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // If highest presentation timestamp for track buffer is set and less than presentation timestamp
</span><span class="cx">         if (trackBuffer.highestPresentationTimestamp.isValid() &amp;&amp; trackBuffer.highestPresentationTimestamp &lt; presentationTimestamp) {
</span><span class="cx">             // Remove all coded frames from track buffer that have a presentation timestamp greater than highest
</span><span class="cx">             // presentation timestamp and less than or equal to frame end timestamp.
</span><del>-            SamplePresentationTimeIsWithinRangeComparator comparator;
-            std::pair&lt;MediaTime, MediaTime&gt; range(trackBuffer.highestPresentationTimestamp, frameEndTimestamp);
-            auto iter_pair = std::equal_range(trackBuffer.samples.begin(), trackBuffer.samples.end(), range, comparator);
-            if (iter_pair.first != trackBuffer.samples.end()) {
</del><ins>+            auto iter_pair = trackBuffer.samples.findSamplesBetweenPresentationTimes(trackBuffer.highestPresentationTimestamp, frameEndTimestamp);
+            if (iter_pair.first != trackBuffer.samples.presentationEnd())
</ins><span class="cx">                 erasedSamples.insert(iter_pair.first, iter_pair.second);
</span><del>-                trackBuffer.samples.erase(iter_pair.first, iter_pair.second);
-            }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // 1.16 Remove decoding dependencies of the coded frames removed in the previous step:
</span><ins>+        SampleMap::MapType dependentSamples;
</ins><span class="cx">         if (!erasedSamples.empty()) {
</span><span class="cx">             // If detailed information about decoding dependencies is available:
</span><span class="cx">             // FIXME: Add support for detailed dependency information
</span><span class="cx"> 
</span><span class="cx">             // Otherwise: Remove all coded frames between the coded frames removed in the previous step
</span><span class="cx">             // and the next random access point after those removed frames.
</span><del>-            auto first_iter = std::upper_bound(trackBuffer.samples.begin(), trackBuffer.samples.end(), *erasedSamples.begin(), SampleLessThanComparator());
-            auto second_iter = std::find_if(first_iter, trackBuffer.samples.end(), SampleIsRandomAccess());
-            if (first_iter != trackBuffer.samples.end()) {
-                trackBuffer.samples.erase(first_iter, second_iter);
-                erasedSamples.insert(first_iter, second_iter);
</del><ins>+            for (auto erasedIt = erasedSamples.begin(), end = erasedSamples.end(); erasedIt != end; ++erasedIt) {
+                auto currentDecodeIter = trackBuffer.samples.findSampleWithDecodeTime(erasedIt-&gt;second-&gt;decodeTime());
+                auto nextSyncIter = trackBuffer.samples.findSyncSampleAfterDecodeIterator(currentDecodeIter);
+                dependentSamples.insert(currentDecodeIter, nextSyncIter);
</ins><span class="cx">             }
</span><ins>+
+
+            RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
+            for (auto erasedIt = erasedSamples.begin(), end = erasedSamples.end(); erasedIt != end; ++erasedIt) {
+                double startTime = erasedIt-&gt;first.toDouble();
+                double endTime = ((erasedIt-&gt;first + erasedIt-&gt;second-&gt;duration()) + microsecond).toDouble();
+                erasedRanges-&gt;add(startTime, endTime);
+                trackBuffer.samples.removeSample(erasedIt-&gt;second.get());
+            }
+
+            for (auto dependentIt = dependentSamples.begin(), end = dependentSamples.end(); dependentIt != end; ++dependentIt) {
+                double startTime = dependentIt-&gt;first.toDouble();
+                double endTime = ((dependentIt-&gt;first + dependentIt-&gt;second-&gt;duration()) + microsecond).toDouble();
+                erasedRanges-&gt;add(startTime, endTime);
+                trackBuffer.samples.removeSample(dependentIt-&gt;second.get());
+            }
+
+            erasedRanges-&gt;invert();
+            m_buffered-&gt;intersectWith(erasedRanges.get());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // 1.17 If spliced audio frame is set:
</span><span class="lines">@@ -910,8 +970,8 @@
</span><span class="cx"> 
</span><span class="cx">         // Otherwise:
</span><span class="cx">         // Add the coded frame with the presentation timestamp, decode timestamp, and frame duration to the track buffer.
</span><del>-        trackBuffer.samples.insert(TrackBuffer::SampleMap::value_type(presentationTimestamp, sample));
-        trackBuffer.decodeQueue.insert(TrackBuffer::SampleMap::value_type(decodeTimestamp, sample));
</del><ins>+        trackBuffer.samples.addSample(sample);
+        trackBuffer.decodeQueue.insert(SampleMap::MapType::value_type(decodeTimestamp, sample));
</ins><span class="cx"> 
</span><span class="cx">         // 1.18 Set last decode timestamp for track buffer to decode timestamp.
</span><span class="cx">         trackBuffer.lastDecodeTimestamp = decodeTimestamp;
</span><span class="lines">@@ -925,17 +985,6 @@
</span><span class="cx">         if (trackBuffer.highestPresentationTimestamp.isInvalid() || frameEndTimestamp &gt; trackBuffer.highestPresentationTimestamp)
</span><span class="cx">             trackBuffer.highestPresentationTimestamp = frameEndTimestamp;
</span><span class="cx"> 
</span><del>-        if (erasedSamples.size()) {
-            RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
-            for (auto iter = erasedSamples.begin(); iter != erasedSamples.end(); ++iter) {
-                double start = iter-&gt;first.toDouble();
-                double end = ((iter-&gt;first + iter-&gt;second-&gt;duration()) + microsecond).toDouble();
-                erasedRanges-&gt;add(start, end);
-            }
-            erasedRanges-&gt;invert();
-            m_buffered-&gt;intersectWith(erasedRanges.get());
-        }
-
</del><span class="cx">         m_buffered-&gt;add(presentationTimestamp.toDouble(), (presentationTimestamp + frameDuration + microsecond).toDouble());
</span><span class="cx"> 
</span><span class="cx">         break;
</span><span class="lines">@@ -1055,6 +1104,43 @@
</span><span class="cx">         m_source-&gt;mediaElement()-&gt;textTrackKindChanged(track);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBuffer::sourceBufferPrivateDidBecomeReadyForMoreSamples(SourceBufferPrivate*)
+{
+    LOG(Media, &quot;SourceBuffer::sourceBufferPrivateDidBecomeReadyForMoreSamples(%p)&quot;, this);
+    provideMediaData();
+}
+
+void SourceBuffer::provideMediaData()
+{
+    if (!m_private-&gt;isReadyForMoreSamples())
+        return;
+
+#if !LOG_DISABLED
+    unsigned enqueuedSamples = 0;
+#endif
+
+    for (auto it = m_trackBufferMap.begin(), end = m_trackBufferMap.end(); it != end; ++it) {
+        TrackBuffer&amp; trackBuffer = it-&gt;value;
+        AtomicString trackID = it-&gt;key;
+        auto sampleIt = trackBuffer.decodeQueue.begin();
+        for (auto sampleEnd = trackBuffer.decodeQueue.end(); sampleIt != sampleEnd; ++sampleIt) {
+            if (!m_private-&gt;isReadyForMoreSamples())
+                break;
+
+            RefPtr&lt;MediaSample&gt; sample = sampleIt-&gt;second;
+            trackBuffer.lastEnqueuedPresentationTime = sample-&gt;presentationTime();
+            m_private-&gt;enqueueSample(sample.release(), trackID);
+#if !LOG_DISABLED
+            ++enqueuedSamples;
+#endif
+
+        }
+        trackBuffer.decodeQueue.erase(trackBuffer.decodeQueue.begin(), sampleIt);
+    }
+
+    LOG(Media, &quot;SourceBuffer::provideMediaData(%p) - Enqueued %u samples&quot;, this, enqueuedSamples);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -107,7 +107,11 @@
</span><span class="cx">     virtual void sourceBufferPrivateDidReceiveSample(SourceBufferPrivate*, PassRefPtr&lt;MediaSample&gt;) OVERRIDE;
</span><span class="cx">     virtual bool sourceBufferPrivateHasAudio(const SourceBufferPrivate*) const OVERRIDE;
</span><span class="cx">     virtual bool sourceBufferPrivateHasVideo(const SourceBufferPrivate*) const OVERRIDE;
</span><ins>+    virtual void sourceBufferPrivateDidBecomeReadyForMoreSamples(SourceBufferPrivate*) OVERRIDE;
+    virtual void sourceBufferPrivateSeekToTime(SourceBufferPrivate*, const MediaTime&amp;);
+    virtual MediaTime sourceBufferPrivateFastSeekTimeForMediaTime(SourceBufferPrivate*, const MediaTime&amp;, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold);
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     // AudioTrackClient
</span><span class="cx">     virtual void audioTrackEnabledChanged(AudioTrack*) OVERRIDE;
</span><span class="cx"> 
</span><span class="lines">@@ -135,6 +139,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool validateInitializationSegment(const InitializationSegment&amp;);
</span><span class="cx"> 
</span><ins>+    void provideMediaData();
+
</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></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -5391,6 +5391,8 @@
</span><span class="cx">                 CDC69DDB16371FD4007C38DF /* WebCoreFullScreenPlaceholderView.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC69DD916371FD3007C38DF /* WebCoreFullScreenPlaceholderView.mm */; };
</span><span class="cx">                 CDC8B5AD1804AE5D0016E685 /* SourceBufferPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC8B5AC1804AE5D0016E685 /* SourceBufferPrivateClient.h */; };
</span><span class="cx">                 CDD525D7145B6DD0008D204D /* JSHTMLMediaElementCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF65CCC145B6AFE00C4C7AA /* JSHTMLMediaElementCustom.cpp */; };
</span><ins>+                CDD7089618359F6F002B3DC6 /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDD7089418359F6E002B3DC6 /* SampleMap.cpp */; };
+                CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; };
</ins><span class="cx">                 CDE3A85417F5FCE600C5BE20 /* AudioTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */; };
</span><span class="cx">                 CDE3A85717F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */; };
</span><span class="cx">                 CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */; };
</span><span class="lines">@@ -12467,6 +12469,8 @@
</span><span class="cx">                 CDC8B5AC1804AE5D0016E685 /* SourceBufferPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceBufferPrivateClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDCE5CD014633BC900D47CCA /* EventTargetFactory.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventTargetFactory.in; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDD1E525167BA56400CE820B /* TextTrackRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackRepresentation.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                CDD7089418359F6E002B3DC6 /* SampleMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SampleMap.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDD7089518359F6F002B3DC6 /* SampleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SampleMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioTrackPrivateAVF.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AudioTrackPrivateAVFObjC.mm; path = objc/AudioTrackPrivateAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioTrackPrivateAVFObjC.h; path = objc/AudioTrackPrivateAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -18463,6 +18467,8 @@
</span><span class="cx">                                 CD8B5A47180E1361008B8E65 /* TextTrackMediaSource.idl */,
</span><span class="cx">                                 CD8B5A45180DFF4E008B8E65 /* VideoTrackMediaSource.h */,
</span><span class="cx">                                 CD8B5A44180DD8D6008B8E65 /* VideoTrackMediaSource.idl */,
</span><ins>+                                CDD7089418359F6E002B3DC6 /* SampleMap.cpp */,
+                                CDD7089518359F6F002B3DC6 /* SampleMap.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = mediasource;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -24389,6 +24395,7 @@
</span><span class="cx">                                 4998AED213FB224D0090B1AA /* ScriptedAnimationController.h in Headers */,
</span><span class="cx">                                 08A484780E5272C500C3FE76 /* ScriptElement.h in Headers */,
</span><span class="cx">                                 E11C9D9B0EB3681200E409DB /* ScriptExecutionContext.h in Headers */,
</span><ins>+                                CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */,
</ins><span class="cx">                                 41002CCD0F66EDEF009E660D /* ScriptFunctionCall.h in Headers */,
</span><span class="cx">                                 9F3B947E12241758005304E7 /* ScriptHeapSnapshot.h in Headers */,
</span><span class="cx">                                 41F066E40F64BCF600A07EAC /* ScriptObject.h in Headers */,
</span><span class="lines">@@ -26160,6 +26167,7 @@
</span><span class="cx">                                 A75E8B8C0E1DE2D6007F2481 /* FEComponentTransfer.cpp in Sources */,
</span><span class="cx">                                 A75E8B8E0E1DE2D6007F2481 /* FEComposite.cpp in Sources */,
</span><span class="cx">                                 84730D781248F0B300D3A9C9 /* FEConvolveMatrix.cpp in Sources */,
</span><ins>+                                CDD7089618359F6F002B3DC6 /* SampleMap.cpp in Sources */,
</ins><span class="cx">                                 50D403C714768C9400D30BB5 /* FECustomFilter.cpp in Sources */,
</span><span class="cx">                                 84730D7A1248F0B300D3A9C9 /* FEDiffuseLighting.cpp in Sources */,
</span><span class="cx">                                 078E090B17D14CEE00420AA1 /* RTCPeerConnection.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -2272,6 +2272,11 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::finishSeek&quot;);
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+    if (m_mediaSource)
+        m_mediaSource-&gt;monitorSourceBuffers();
+#endif
+
</ins><span class="cx">     // 4.8.10.9 Seeking
</span><span class="cx">     // 14 - Set the seeking IDL attribute to false.
</span><span class="cx">     m_seeking = false;
</span><span class="lines">@@ -3548,6 +3553,9 @@
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx">             parameters.keySystem = system;
</span><span class="cx"> #endif
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+            parameters.isMediaSource = mediaURL.protocolIs(mediaSourceBlobProtocol);
+#endif
</ins><span class="cx">             if (!MediaPlayer::supportsType(parameters, this))
</span><span class="cx">                 goto check_again;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaSource.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaSource.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/html/HTMLMediaSource.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;URLRegistry.h&quot;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><ins>+#include &lt;wtf/MediaTime.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -61,6 +62,7 @@
</span><span class="cx">     virtual PassRefPtr&lt;TimeRanges&gt; buffered() const = 0;
</span><span class="cx">     virtual void refHTMLMediaSource() = 0;
</span><span class="cx">     virtual void derefHTMLMediaSource() = 0;
</span><ins>+    virtual void monitorSourceBuffers() = 0;
</ins><span class="cx"> 
</span><span class="cx">     // URLRegistrable
</span><span class="cx">     virtual URLRegistry&amp; registry() const OVERRIDE { return *s_registry; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMediaSampleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MediaSample.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MediaSample.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/MediaSample.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/MediaTime.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><ins>+#include &lt;wtf/text/AtomicString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsSourceBufferPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -35,9 +35,11 @@
</span><span class="cx"> #include &quot;MediaPlayer.h&quot;
</span><span class="cx"> #include &quot;TimeRanges.h&quot;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class MediaSample;
</ins><span class="cx"> class SourceBufferPrivateClient;
</span><span class="cx"> class TimeRanges;
</span><span class="cx"> 
</span><span class="lines">@@ -60,6 +62,11 @@
</span><span class="cx">     virtual void setReadyState(MediaPlayer::ReadyState) = 0;
</span><span class="cx">     virtual void evictCodedFrames() = 0;
</span><span class="cx">     virtual bool isFull() = 0;
</span><ins>+
+    virtual void flushAndEnqueueNonDisplayingSamples(Vector&lt;RefPtr&lt;MediaSample&gt;&gt;, AtomicString) { }
+    virtual void enqueueSample(PassRefPtr&lt;MediaSample&gt;, AtomicString) { }
+    virtual bool isReadyForMoreSamples() { return false; }
+    virtual void setActive(bool) { }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsSourceBufferPrivateClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/SourceBufferPrivateClient.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/SourceBufferPrivateClient.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/graphics/SourceBufferPrivateClient.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -72,6 +72,12 @@
</span><span class="cx">     virtual void sourceBufferPrivateDidReceiveSample(SourceBufferPrivate*, PassRefPtr&lt;MediaSample&gt;) = 0;
</span><span class="cx">     virtual bool sourceBufferPrivateHasAudio(const SourceBufferPrivate*) const = 0;
</span><span class="cx">     virtual bool sourceBufferPrivateHasVideo(const SourceBufferPrivate*) const = 0;
</span><ins>+
+    virtual void sourceBufferPrivateDidBecomeReadyForMoreSamples(SourceBufferPrivate*) = 0;
+
+    virtual MediaTime sourceBufferPrivateFastSeekTimeForMediaTime(SourceBufferPrivate*, const MediaTime&amp; time, const MediaTime&amp;, const MediaTime&amp;) { return time; }
+    virtual void sourceBufferPrivateSeekToTime(SourceBufferPrivate*, const MediaTime&amp;) { };
+
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx"> 
</span><span class="cx"> MockMediaPlayerMediaSource::MockMediaPlayerMediaSource(MediaPlayer* player)
</span><span class="cx">     : m_player(player)
</span><del>-    , m_currentTime(0)
</del><ins>+    , m_currentTime(MediaTime::zeroTime())
</ins><span class="cx">     , m_duration(0)
</span><span class="cx">     , m_readyState(MediaPlayer::HaveNothing)
</span><span class="cx">     , m_networkState(MediaPlayer::Empty)
</span><span class="lines">@@ -161,6 +161,11 @@
</span><span class="cx">     return m_readyState;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+double MockMediaPlayerMediaSource::maxTimeSeekableDouble() const
+{
+    return m_duration;
+}
+
</ins><span class="cx"> PassRefPtr&lt;TimeRanges&gt; MockMediaPlayerMediaSource::buffered() const
</span><span class="cx"> {
</span><span class="cx">     return m_mediaSource ? m_mediaSource-&gt;buffered() : TimeRanges::create();
</span><span class="lines">@@ -181,7 +186,7 @@
</span><span class="cx"> 
</span><span class="cx"> double MockMediaPlayerMediaSource::currentTimeDouble() const
</span><span class="cx"> {
</span><del>-    return m_currentTime;
</del><ins>+    return m_currentTime.toDouble();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double MockMediaPlayerMediaSource::durationDouble() const
</span><span class="lines">@@ -189,9 +194,13 @@
</span><span class="cx">     return m_duration;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockMediaPlayerMediaSource::seekDouble(double time)
</del><ins>+void MockMediaPlayerMediaSource::seekWithTolerance(double time, double negativeTolerance, double positiveTolerance)
</ins><span class="cx"> {
</span><del>-    m_currentTime = std::min(time, m_duration);
</del><ins>+    if (!negativeTolerance &amp;&amp; !positiveTolerance) {
+        m_currentTime = MediaTime::createWithDouble(time);
+        m_mediaSourcePrivate-&gt;seekToTime(MediaTime::createWithDouble(time));
+    } else
+        m_currentTime = m_mediaSourcePrivate-&gt;seekToTime(MediaTime::createWithDouble(time), MediaTime::createWithDouble(negativeTolerance), MediaTime::createWithDouble(positiveTolerance));
</ins><span class="cx">     m_player-&gt;timeChanged();
</span><span class="cx"> 
</span><span class="cx">     if (m_playing)
</span><span class="lines">@@ -201,11 +210,11 @@
</span><span class="cx"> void MockMediaPlayerMediaSource::advanceCurrentTime()
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;TimeRanges&gt; buffered = this-&gt;buffered();
</span><del>-    size_t pos = buffered-&gt;find(m_currentTime);
</del><ins>+    size_t pos = buffered-&gt;find(m_currentTime.toDouble());
</ins><span class="cx">     if (pos == notFound)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_currentTime = std::min(m_duration, buffered-&gt;end(pos, IGNORE_EXCEPTION));
</del><ins>+    m_currentTime = MediaTime::createWithDouble(std::min(m_duration, buffered-&gt;end(pos, IGNORE_EXCEPTION)));
</ins><span class="cx">     m_player-&gt;timeChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;MediaPlayerPrivate.h&quot;
</span><ins>+#include &lt;wtf/MediaTime.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -67,19 +68,20 @@
</span><span class="cx">     virtual bool seeking() const OVERRIDE;
</span><span class="cx">     virtual bool paused() const OVERRIDE;
</span><span class="cx">     virtual MediaPlayer::NetworkState networkState() const OVERRIDE;
</span><ins>+    virtual double maxTimeSeekableDouble() const OVERRIDE;
</ins><span class="cx">     virtual PassRefPtr&lt;TimeRanges&gt; buffered() const OVERRIDE;
</span><span class="cx">     virtual bool didLoadingProgress() const OVERRIDE;
</span><span class="cx">     virtual void setSize(const IntSize&amp;) OVERRIDE;
</span><span class="cx">     virtual void paint(GraphicsContext*, const IntRect&amp;) OVERRIDE;
</span><span class="cx">     virtual double currentTimeDouble() const OVERRIDE;
</span><span class="cx">     virtual double durationDouble() const OVERRIDE;
</span><del>-    virtual void seekDouble(double time) OVERRIDE;
</del><ins>+    virtual void seekWithTolerance(double time, double, double) OVERRIDE;
</ins><span class="cx"> 
</span><span class="cx">     MediaPlayer* m_player;
</span><span class="cx">     RefPtr&lt;HTMLMediaSource&gt; m_mediaSource;
</span><span class="cx">     RefPtr&lt;MockMediaSourcePrivate&gt; m_mediaSourcePrivate;
</span><span class="cx"> 
</span><del>-    double m_currentTime;
</del><ins>+    MediaTime m_currentTime;
</ins><span class="cx">     double m_duration;
</span><span class="cx">     MediaPlayer::ReadyState m_readyState;
</span><span class="cx">     MediaPlayer::NetworkState m_networkState;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -145,6 +145,27 @@
</span><span class="cx">     return std::any_of(m_activeSourceBuffers.begin(), m_activeSourceBuffers.end(), MockSourceBufferPrivateHasVideo);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockMediaSourcePrivate::seekToTime(const MediaTime&amp; time)
+{
+    for (auto it = m_activeSourceBuffers.begin(), end = m_activeSourceBuffers.end(); it != end; ++it)
+        (*it)-&gt;seekToTime(time);
+}
+
+MediaTime MockMediaSourcePrivate::seekToTime(const MediaTime&amp; targetTime, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold)
+{
+    MediaTime seekTime = targetTime;
+    for (auto it = m_activeSourceBuffers.begin(), end = m_activeSourceBuffers.end(); it != end; ++it) {
+        MediaTime sourceSeekTime = (*it)-&gt;fastSeekTimeForMediaTime(targetTime, negativeThreshold, positiveThreshold);
+        if (abs(targetTime - sourceSeekTime) &gt; abs(targetTime - seekTime))
+            seekTime = sourceSeekTime;
+    }
+
+    for (auto it = m_activeSourceBuffers.begin(), end = m_activeSourceBuffers.end(); it != end; ++it)
+        (*it)-&gt;seekToTime(seekTime);
+    
+    return seekTime;
+}
+
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;MediaSourcePrivate.h&quot;
</span><ins>+#include &lt;wtf/MediaTime.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -48,6 +49,9 @@
</span><span class="cx"> 
</span><span class="cx">     MockMediaPlayerMediaSource* player() const { return m_player; }
</span><span class="cx"> 
</span><ins>+    void seekToTime(const MediaTime&amp;);
+    MediaTime seekToTime(const MediaTime&amp;, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold);
+
</ins><span class="cx"> private:
</span><span class="cx">     MockMediaSourcePrivate(MockMediaPlayerMediaSource*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">     virtual MediaTime duration() const OVERRIDE { return m_box.duration(); }
</span><span class="cx">     virtual AtomicString trackID() const OVERRIDE { return m_id; }
</span><span class="cx"> 
</span><del>-    virtual SampleFlags flags() const OVERRIDE { return None; }
</del><ins>+    virtual SampleFlags flags() const OVERRIDE;
</ins><span class="cx">     virtual PlatformSample platformSample() OVERRIDE;
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -65,6 +65,14 @@
</span><span class="cx">     AtomicString m_id;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+MediaSample::SampleFlags MockMediaSample::flags() const
+{
+    unsigned flags = None;
+    if (m_box.flags() &amp; MockSampleBox::IsSync)
+        flags |= IsSync;
+    return SampleFlags(flags);
+}
+
</ins><span class="cx"> PlatformSample MockMediaSample::platformSample()
</span><span class="cx"> {
</span><span class="cx">     PlatformSample sample = { PlatformSample::MockSampleBoxType, { &amp;m_box } };
</span><span class="lines">@@ -202,6 +210,11 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockSourceBufferPrivate::setActive(bool isActive)
+{
+    m_parent-&gt;sourceBufferPrivateDidChangeActiveState(this, isActive);
+}
+
</ins><span class="cx"> bool MockSourceBufferPrivate::hasVideo() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_client)
</span><span class="lines">@@ -218,7 +231,21 @@
</span><span class="cx">     return m_client-&gt;sourceBufferPrivateHasAudio(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+MediaTime MockSourceBufferPrivate::fastSeekTimeForMediaTime(const MediaTime&amp; time, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold)
+{
+    if (m_client)
+        return m_client-&gt;sourceBufferPrivateFastSeekTimeForMediaTime(this, time, negativeThreshold, positiveThreshold);
+    return time;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockSourceBufferPrivate::seekToTime(const MediaTime&amp; time)
+{
+    if (m_client)
+        m_client-&gt;sourceBufferPrivateSeekToTime(this, time);
+}
+
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h (159518 => 159519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2013-11-19 21:37:02 UTC (rev 159518)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2013-11-19 21:39:43 UTC (rev 159519)
</span><span class="lines">@@ -53,6 +53,9 @@
</span><span class="cx">     bool hasVideo() const;
</span><span class="cx">     bool hasAudio() const;
</span><span class="cx"> 
</span><ins>+    void seekToTime(const MediaTime&amp;);
+    MediaTime fastSeekTimeForMediaTime(const MediaTime&amp;, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold);
+
</ins><span class="cx"> private:
</span><span class="cx">     explicit MockSourceBufferPrivate(MockMediaSourcePrivate*);
</span><span class="cx"> 
</span><span class="lines">@@ -66,6 +69,11 @@
</span><span class="cx">     virtual void evictCodedFrames() OVERRIDE;
</span><span class="cx">     virtual bool isFull() OVERRIDE;
</span><span class="cx"> 
</span><ins>+    virtual void flushAndEnqueueNonDisplayingSamples(Vector&lt;RefPtr&lt;MediaSample&gt;&gt;, AtomicString) OVERRIDE { }
+    virtual void enqueueSample(PassRefPtr&lt;MediaSample&gt;, AtomicString) OVERRIDE { }
+    virtual bool isReadyForMoreSamples() OVERRIDE { return true; }
+    virtual void setActive(bool) OVERRIDE;
+
</ins><span class="cx">     void didReceiveInitializationSegment(const MockInitializationBox&amp;);
</span><span class="cx">     void didReceiveSample(const MockSampleBox&amp;);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>