<!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>[206567] branches/safari-602.2.14.0-branch</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/206567">206567</a></dd>
<dt>Author</dt> <dd>bshafiei@apple.com</dd>
<dt>Date</dt> <dd>2016-09-28 17:54:32 -0700 (Wed, 28 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/206518">r206518</a>. rdar://problem/28505032</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari6022140branchLayoutTestsChangeLog">branches/safari-602.2.14.0-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreChangeLog">branches/safari-602.2.14.0-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreModulesmediasourceSourceBuffercpp">branches/safari-602.2.14.0-branch/Source/WebCore/Modules/mediasource/SourceBuffer.cpp</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformgraphicsSourceBufferPrivateh">branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/SourceBufferPrivate.h</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh">branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm">branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformgraphicsgstreamerSourceBufferPrivateGStreamercpp">branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformgraphicsgstreamerSourceBufferPrivateGStreamerh">branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp">branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh">branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h</a></li>
<li><a href="#branchessafari6022140branchSourceWebCoreplatformspimacAVFoundationSPIh">branches/safari-602.2.14.0-branch/Source/WebCore/platform/spi/mac/AVFoundationSPI.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari6022140branchLayoutTestsmediamediasourcemediasourceabortresetsparserexpectedtxt">branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser-expected.txt</a></li>
<li><a href="#branchessafari6022140branchLayoutTestsmediamediasourcemediasourceabortresetsparserhtml">branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari6022140branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/LayoutTests/ChangeLog (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/LayoutTests/ChangeLog        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/LayoutTests/ChangeLog        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-09-28  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
+        Merge r206518. rdar://problem/28505032
+
+    2016-09-28  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+            [MSE][Mac] In SourceBufferPrivateAVFObjC::abort(), support reseting parser to the last appended initialization segment.
+            https://bugs.webkit.org/show_bug.cgi?id=135164
+
+            Reviewed by Eric Carlson.
+
+            * media/media-source/media-source-abort-resets-parser-expected.txt: Added.
+            * media/media-source/media-source-abort-resets-parser.html: Added.
+
</ins><span class="cx"> 2016-09-23  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merge r203982. rdar://problem/27547583
</span></span></pre></div>
<a id="branchessafari6022140branchLayoutTestsmediamediasourcemediasourceabortresetsparserexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser-expected.txt (0 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser-expected.txt                                (rev 0)
+++ branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser-expected.txt        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+This tests the ability of the SourceBuffer to reset the parser after an abort(). A SourceBuffer in this state should be able to accept a new initialization segment or a new media segment.
+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(source.duration = loader.duration())
+RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(update)
+Append a partial media segment.
+RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2)))
+EVENT(update)
+Abort and append a new initialization segment.
+RUN(sourceBuffer.abort())
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(update)
+Append a partial media segment.
+RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2)))
+EVENT(update)
+Abort and append a new media segment.
+RUN(sourceBuffer.abort())
+RUN(sourceBuffer.appendBuffer(loader.mediaSegment(1)))
+EVENT(update)
+END OF TEST
+
</ins></span></pre></div>
<a id="branchessafari6022140branchLayoutTestsmediamediasourcemediasourceabortresetsparserhtml"></a>
<div class="addfile"><h4>Added: branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser.html (0 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser.html                                (rev 0)
+++ branches/safari-602.2.14.0-branch/LayoutTests/media/media-source/media-source-abort-resets-parser.html        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;title&gt;media-source-abort-resets-parser&lt;/title&gt;
+    &lt;script src=&quot;media-source-loader.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;../video-test.js&quot;&gt;&lt;/script&gt;
+    &lt;script&gt;
+    var loader;
+    var source;
+    var sourceBuffer;
+
+    function runTest() {
+        findMediaElement();
+
+        loader = new MediaSourceLoader('content/test-fragmented-manifest.json');
+        loader.onload = mediaDataLoaded;
+        loader.onerror = mediaDataLoadingFailed;
+    }
+
+    function mediaDataLoadingFailed() {
+        failTest('Media data loading failed');
+    }
+
+    function mediaDataLoaded() {
+        source = new MediaSource();
+        waitForEvent('sourceopen', sourceOpen, false, false, source);
+        waitForEventAndFail('error');
+        run('video.src = URL.createObjectURL(source)');
+    }
+
+    function sourceOpen() {
+        run('source.duration = loader.duration()');
+        run('sourceBuffer = source.addSourceBuffer(loader.type())');
+        waitForEventOn(sourceBuffer, 'update', sourceInitialized, false, true);
+        run('sourceBuffer.appendBuffer(loader.initSegment())');
+    }
+
+    function sourceInitialized() {
+        waitForEventOn(sourceBuffer, 'update', partialMediaSegmentAppended1, false, true);
+        consoleWrite('Append a partial media segment.')
+        run('sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2))');
+    }
+
+    function partialMediaSegmentAppended1() {
+        consoleWrite('Abort and append a new initialization segment.')
+        run('sourceBuffer.abort()');
+        run('sourceBuffer.appendBuffer(loader.initSegment())');
+        waitForEventOn(sourceBuffer, 'update', initSegmentAppended, false, true);
+    }
+
+    function initSegmentAppended() {
+        waitForEventOn(sourceBuffer, 'update', partialMediaSegmentAppended2, false, true);
+        consoleWrite('Append a partial media segment.')
+        run('sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2))');
+    }
+
+    function partialMediaSegmentAppended2() {
+        consoleWrite('Abort and append a new media segment.')
+        run('sourceBuffer.abort()');
+        run('sourceBuffer.appendBuffer(loader.mediaSegment(1))');
+        waitForEventOn(sourceBuffer, 'update', endTest, false, true);
+    }
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;div&gt;
+        This tests the ability of the SourceBuffer to reset the parser after an abort(). A SourceBuffer in this state should be able to accept
+        a new initialization segment or a new media segment.
+    &lt;/div&gt;
+    &lt;video controls&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/ChangeLog (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/ChangeLog        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/ChangeLog        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2016-09-28  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
+        Merge r206518. rdar://problem/28505032
+
+    2016-09-28  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+            [MSE][Mac] In SourceBufferPrivateAVFObjC::abort(), support reseting parser to the last appended initialization segment.
+            https://bugs.webkit.org/show_bug.cgi?id=135164
+
+            Reviewed by Eric Carlson.
+
+            Test: media/media-source/media-source-abort-resets-parser.html
+
+            Use the -[AVStreamDataParser appendStreamData:withFlags:] to implement &quot;resetting&quot; the parser. In this case,
+            the parser isn't explicitly reset during resetParserState(), but rather a flag is set so that the next append
+            signals a data discontinuity, and the parser is reset at that point.
+
+            Because a previous append operation may be in-flight during this abort(), care must be taken to invalidate any
+            operations which may have already started on a background thread. So SourceBufferPrivateAVFObjC will use a
+            separate WeakPtrFactory for its append operations, will invalidate any outstanding WeakPtrs during an abort(),
+            and will block until the previous append() operation completes.
+
+            This will require the WebAVStreamDataParserListener object to occasionally have it's WeakPtr pointing back to the
+            SourceBufferPrivateAVFObjC to be reset after an abort(), so make that ivar an @property. Rather than passing a
+            RetainPtr to itself in all the callbacks it handles, the WebAVStreamDataParserListener can just pass in a copy
+            of its own WeakPtr (which may be invalidated during an abort()).
+
+            Break the distinct operations of &quot;abort()&quot; and &quot;resetParserState()&quot; into their own methods in SourceBufferPrivate
+            and all its subclasses.
+
+            * Modules/mediasource/SourceBuffer.cpp:
+            (WebCore::SourceBuffer::resetParserState):
+            (WebCore::SourceBuffer::abortIfUpdating):
+            * platform/graphics/SourceBufferPrivate.h:
+            * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+            * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+            (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]):
+            (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]):
+            (-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]):
+            (-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]):
+            (-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]):
+            (-[WebAVStreamDataParserListener streamDataParserWillProvideContentKeyRequestInitializationData:forTrackID:]):
+            (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]):
+            (WebCore::SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC):
+            (WebCore::SourceBufferPrivateAVFObjC::append):
+            (WebCore::SourceBufferPrivateAVFObjC::abort):
+            (WebCore::SourceBufferPrivateAVFObjC::resetParserState):
+            (-[WebAVStreamDataParserListener initWithParser:parent:]): Deleted.
+            * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp:
+            (WebCore::SourceBufferPrivateGStreamer::resetParserState):
+            * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h:
+            * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+            (WebCore::MockSourceBufferPrivate::resetParserState):
+            * platform/mock/mediasource/MockSourceBufferPrivate.h:
+            * platform/spi/mac/AVFoundationSPI.h:
+
</ins><span class="cx"> 2016-09-27  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merge r206454. rdar://problem/28484193
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -282,7 +282,7 @@
</span><span class="cx">     // 7. Set append state to WAITING_FOR_SEGMENT.
</span><span class="cx">     m_appendState = WaitingForSegment;
</span><span class="cx"> 
</span><del>-    m_private-&gt;abort();
</del><ins>+    m_private-&gt;resetParserState();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SourceBuffer::abort(ExceptionCode&amp; ec)
</span><span class="lines">@@ -380,6 +380,7 @@
</span><span class="cx">     // 3.1. Abort the buffer append and stream append loop algorithms if they are running.
</span><span class="cx">     m_appendBufferTimer.stop();
</span><span class="cx">     m_pendingAppendData.clear();
</span><ins>+    m_private-&gt;abort();
</ins><span class="cx"> 
</span><span class="cx">     m_removeTimer.stop();
</span><span class="cx">     m_pendingRemoveStart = MediaTime::invalidTime();
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformgraphicsSourceBufferPrivateh"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/SourceBufferPrivate.h (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/SourceBufferPrivate.h        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/SourceBufferPrivate.h        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void append(const unsigned char* data, unsigned length) = 0;
</span><span class="cx">     virtual void abort() = 0;
</span><ins>+    virtual void resetParserState() = 0;
</ins><span class="cx">     virtual void removedFromMediaSource() = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual MediaPlayer::ReadyState readyState() const = 0;
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;SourceBufferPrivate.h&quot;
</span><ins>+#include &lt;dispatch/group.h&gt;
</ins><span class="cx"> #include &lt;dispatch/semaphore.h&gt;
</span><span class="cx"> #include &lt;wtf/Deque.h&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="lines">@@ -115,6 +116,7 @@
</span><span class="cx">     void setClient(SourceBufferPrivateClient*) override;
</span><span class="cx">     void append(const unsigned char* data, unsigned length) override;
</span><span class="cx">     void abort() override;
</span><ins>+    void resetParserState() override;
</ins><span class="cx">     void removedFromMediaSource() override;
</span><span class="cx">     MediaPlayer::ReadyState readyState() const override;
</span><span class="cx">     void setReadyState(MediaPlayer::ReadyState) override;
</span><span class="lines">@@ -139,6 +141,7 @@
</span><span class="cx">     Vector&lt;SourceBufferPrivateAVFObjCErrorClient*&gt; m_errorClients;
</span><span class="cx"> 
</span><span class="cx">     WeakPtrFactory&lt;SourceBufferPrivateAVFObjC&gt; m_weakFactory;
</span><ins>+    WeakPtrFactory&lt;SourceBufferPrivateAVFObjC&gt; m_appendWeakFactory;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVStreamDataParser&gt; m_parser;
</span><span class="cx">     RetainPtr&lt;AVAsset&gt; m_asset;
</span><span class="lines">@@ -148,6 +151,7 @@
</span><span class="cx">     RetainPtr&lt;WebAVSampleBufferErrorListener&gt; m_errorListener;
</span><span class="cx">     RetainPtr&lt;NSError&gt; m_hdcpError;
</span><span class="cx">     OSObjectPtr&lt;dispatch_semaphore_t&gt; m_hasSessionSemaphore;
</span><ins>+    OSObjectPtr&lt;dispatch_group_t&gt; m_isAppendingGroup;
</ins><span class="cx"> 
</span><span class="cx">     MediaSourcePrivateAVFObjC* m_mediaSource;
</span><span class="cx">     SourceBufferPrivateClient* m_client;
</span><span class="lines">@@ -155,6 +159,7 @@
</span><span class="cx"> 
</span><span class="cx">     FloatSize m_cachedSize;
</span><span class="cx">     bool m_parsingSucceeded;
</span><ins>+    bool m_parserStateWasReset { false };
</ins><span class="cx">     int m_enabledVideoTrackID;
</span><span class="cx">     int m_protectedTrackID;
</span><span class="cx"> };
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -130,6 +130,7 @@
</span><span class="cx">     WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; _parent;
</span><span class="cx">     AVStreamDataParser* _parser;
</span><span class="cx"> }
</span><ins>+@property (assign) WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; parent;
</ins><span class="cx"> - (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt;)parent;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="lines">@@ -147,6 +148,8 @@
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+@synthesize parent=_parent;
+
</ins><span class="cx"> - (void)dealloc
</span><span class="cx"> {
</span><span class="cx">     [_parser setDelegate:nil];
</span><span class="lines">@@ -165,12 +168,11 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVAsset*&gt; protectedAsset = asset;
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didParseStreamDataAsAsset(protectedAsset.get());
</del><ins>+    callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] {
+        if (parent)
+            parent-&gt;didParseStreamDataAsAsset(protectedAsset.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -181,12 +183,11 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVAsset*&gt; protectedAsset = asset;
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didParseStreamDataAsAsset(protectedAsset.get());
</del><ins>+    callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] {
+        if (parent)
+            parent-&gt;didParseStreamDataAsAsset(protectedAsset.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -196,12 +197,11 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSError&gt; protectedError = error;
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedError = WTFMove(protectedError)] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didFailToParseStreamDataWithError(protectedError.get());
</del><ins>+    callOnMainThread([parent = _parent, protectedError = WTFMove(protectedError)] {
+        if (parent)
+            parent-&gt;didFailToParseStreamDataWithError(protectedError.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -211,13 +211,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; protectedSample = sample;
</span><span class="cx">     String mediaType = nsMediaType;
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags);
</del><ins>+    callOnMainThread([parent = _parent, protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {
+        if (parent)
+            parent-&gt;didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -227,12 +226,11 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     String mediaType = nsMediaType;
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), trackID, mediaType] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didReachEndOfTrackWithTrackID(trackID, mediaType);
</del><ins>+    callOnMainThread([parent = _parent, trackID, mediaType] {
+        if (parent)
+            parent-&gt;didReachEndOfTrackWithTrackID(trackID, mediaType);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -245,10 +243,9 @@
</span><span class="cx"> 
</span><span class="cx">     // We must call synchronously to the main thread, as the AVStreamSession must be associated
</span><span class="cx">     // with the streamDataParser before the delegate method returns.
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
-    dispatch_sync(dispatch_get_main_queue(), [strongSelf, trackID]() {
-        if (strongSelf-&gt;_parent)
-            strongSelf-&gt;_parent-&gt;willProvideContentKeyRequestInitializationDataForTrackID(trackID);
</del><ins>+    dispatch_sync(dispatch_get_main_queue(), [parent = _parent, trackID]() {
+        if (parent)
+            parent-&gt;willProvideContentKeyRequestInitializationDataForTrackID(trackID);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -258,12 +255,11 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RetainPtr&lt;WebAVStreamDataParserListener&gt; protectedSelf = self;
</del><span class="cx"> 
</span><span class="cx">     OSObjectPtr&lt;dispatch_semaphore_t&gt; hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0));
</span><del>-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedInitData = RetainPtr&lt;NSData&gt;(initData), trackID, hasSessionSemaphore] {
-        if (protectedSelf-&gt;_parent)
-            protectedSelf-&gt;_parent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore);
</del><ins>+    callOnMainThread([parent = _parent, protectedInitData = RetainPtr&lt;NSData&gt;(initData), trackID, hasSessionSemaphore] {
+        if (parent)
+            parent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore);
</ins><span class="cx">     });
</span><span class="cx">     dispatch_semaphore_wait(hasSessionSemaphore.get(), DISPATCH_TIME_FOREVER);
</span><span class="cx"> }
</span><span class="lines">@@ -582,9 +578,11 @@
</span><span class="cx"> 
</span><span class="cx"> SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC(MediaSourcePrivateAVFObjC* parent)
</span><span class="cx">     : m_weakFactory(this)
</span><ins>+    , m_appendWeakFactory(this)
</ins><span class="cx">     , m_parser(adoptNS([allocAVStreamDataParserInstance() init]))
</span><span class="cx">     , m_delegate(adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()]))
</span><span class="cx">     , m_errorListener(adoptNS([[WebAVSampleBufferErrorListener alloc] initWithParent:this]))
</span><ins>+    , m_isAppendingGroup(adoptOSObject(dispatch_group_create()))
</ins><span class="cx">     , m_mediaSource(parent)
</span><span class="cx">     , m_client(0)
</span><span class="cx">     , m_parsingSucceeded(true)
</span><span class="lines">@@ -772,21 +770,26 @@
</span><span class="cx">     LOG(MediaSource, &quot;SourceBufferPrivateAVFObjC::append(%p) - data:%p, length:%d&quot;, this, data, length);
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSData&gt; nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]);
</span><del>-    WeakPtr&lt;SourceBufferPrivateAVFObjC&gt; weakThis = createWeakPtr();
</del><ins>+    WeakPtr&lt;SourceBufferPrivateAVFObjC&gt; weakThis = m_appendWeakFactory.createWeakPtr();
</ins><span class="cx">     RetainPtr&lt;AVStreamDataParser&gt; parser = m_parser;
</span><span class="cx">     RetainPtr&lt;WebAVStreamDataParserListener&gt; delegate = m_delegate;
</span><span class="cx"> 
</span><span class="cx">     m_parsingSucceeded = true;
</span><ins>+    dispatch_group_enter(m_isAppendingGroup.get());
</ins><span class="cx"> 
</span><del>-    dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate] {
</del><ins>+    dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate, isAppendingGroup = m_isAppendingGroup, parserStateWasReset = m_parserStateWasReset] {
+        if (parserStateWasReset)
+            [parser appendStreamData:nsData.get() withFlags:AVStreamDataParserStreamDataDiscontinuity];
+        else
+            [parser appendStreamData:nsData.get()];
</ins><span class="cx"> 
</span><del>-        [parser appendStreamData:nsData.get()];
-
</del><span class="cx">         callOnMainThread([weakThis] {
</span><span class="cx">             if (weakThis)
</span><span class="cx">                 weakThis-&gt;appendCompleted();
</span><span class="cx">         });
</span><ins>+        dispatch_group_leave(isAppendingGroup.get());
</ins><span class="cx">     });
</span><ins>+    m_parserStateWasReset = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::appendCompleted()
</span><span class="lines">@@ -800,12 +803,19 @@
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::abort()
</span><span class="cx"> {
</span><del>-    // The parser does not have a mechanism for resetting to a clean state, so destroy and re-create it.
-    // FIXME(135164): Support resetting parser to the last appended initialization segment.
-    destroyParser();
</del><ins>+    // The parsing queue may be blocked waiting for the main thread to provide it a AVStreamSession. We
+    // were asked to abort, and that cancels all outstanding append operations. Without cancelling this
+    // semaphore, the m_isAppendingGroup wait operation will deadlock.
+    if (m_hasSessionSemaphore)
+        dispatch_semaphore_signal(m_hasSessionSemaphore.get());
+    dispatch_group_wait(m_isAppendingGroup.get(), DISPATCH_TIME_FOREVER);
+    m_appendWeakFactory.revokeAll();
+    m_delegate.get().parent = m_appendWeakFactory.createWeakPtr();
+}
</ins><span class="cx"> 
</span><del>-    m_parser = adoptNS([allocAVStreamDataParserInstance() init]);
-    m_delegate = adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()]);
</del><ins>+void SourceBufferPrivateAVFObjC::resetParserState()
+{
+    m_parserStateWasReset = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::destroyParser()
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformgraphicsgstreamerSourceBufferPrivateGStreamercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -75,6 +75,11 @@
</span><span class="cx">     notImplemented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBufferPrivateGStreamer::resetParserState()
+{
+    notImplemented();
+}
+
</ins><span class="cx"> void SourceBufferPrivateGStreamer::removedFromMediaSource()
</span><span class="cx"> {
</span><span class="cx">     m_client-&gt;removedFromMediaSource(this);
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformgraphicsgstreamerSourceBufferPrivateGStreamerh"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void append(const unsigned char* data, unsigned length);
</span><span class="cx">     virtual void abort();
</span><ins>+    virtual void resetParserState();
</ins><span class="cx">     virtual void removedFromMediaSource();
</span><span class="cx"> 
</span><span class="cx">     virtual MediaPlayer::ReadyState readyState() const;
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -198,6 +198,10 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockSourceBufferPrivate::resetParserState()
+{
+}
+
</ins><span class="cx"> void MockSourceBufferPrivate::removedFromMediaSource()
</span><span class="cx"> {
</span><span class="cx">     if (m_mediaSource)
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">     void setClient(SourceBufferPrivateClient*) override;
</span><span class="cx">     void append(const unsigned char* data, unsigned length) override;
</span><span class="cx">     void abort() override;
</span><ins>+    void resetParserState() override;
</ins><span class="cx">     void removedFromMediaSource() override;
</span><span class="cx">     MediaPlayer::ReadyState readyState() const override;
</span><span class="cx">     void setReadyState(MediaPlayer::ReadyState) override;
</span></span></pre></div>
<a id="branchessafari6022140branchSourceWebCoreplatformspimacAVFoundationSPIh"></a>
<div class="modfile"><h4>Modified: branches/safari-602.2.14.0-branch/Source/WebCore/platform/spi/mac/AVFoundationSPI.h (206566 => 206567)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.2.14.0-branch/Source/WebCore/platform/spi/mac/AVFoundationSPI.h        2016-09-29 00:54:27 UTC (rev 206566)
+++ branches/safari-602.2.14.0-branch/Source/WebCore/platform/spi/mac/AVFoundationSPI.h        2016-09-29 00:54:32 UTC (rev 206567)
</span><span class="lines">@@ -116,9 +116,14 @@
</span><span class="cx">     AVStreamDataParserOutputMediaDataReserved = 1 &lt;&lt; 0
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+typedef NS_ENUM(NSUInteger, AVStreamDataParserStreamDataFlags) {
+    AVStreamDataParserStreamDataDiscontinuity = 1 &lt;&lt; 0,
+};
+
</ins><span class="cx"> @interface AVStreamDataParser : NSObject
</span><span class="cx"> - (void)setDelegate:(nullable id&lt;AVStreamDataParserOutputHandling&gt;)delegate;
</span><span class="cx"> - (void)appendStreamData:(NSData *)data;
</span><ins>+- (void)appendStreamData:(NSData *)data withFlags:(AVStreamDataParserStreamDataFlags)flags;
</ins><span class="cx"> - (void)setShouldProvideMediaData:(BOOL)shouldProvideMediaData forTrackID:(CMPersistentTrackID)trackID;
</span><span class="cx"> - (BOOL)shouldProvideMediaDataForTrackID:(CMPersistentTrackID)trackID;
</span><span class="cx"> - (void)providePendingMediaData;
</span></span></pre>
</div>
</div>

</body>
</html>