<!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 <bshafiei@apple.com>
+
+ Merge r206518. rdar://problem/28505032
+
+ 2016-09-28 Jer Noble <jer.noble@apple.com>
+
+ [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 <bshafiei@apple.com>
</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>+<!DOCTYPE html>
+<html>
+<head>
+ <title>media-source-abort-resets-parser</title>
+ <script src="media-source-loader.js"></script>
+ <script src="../video-test.js"></script>
+ <script>
+ 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);
+ }
+ </script>
+</head>
+<body onload="runTest()">
+ <div>
+ 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.
+ </div>
+ <video controls></video>
+</body>
+</html>
</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 <bshafiei@apple.com>
+
+ Merge r206518. rdar://problem/28505032
+
+ 2016-09-28 Jer Noble <jer.noble@apple.com>
+
+ [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 "resetting" 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 "abort()" and "resetParserState()" 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 <bshafiei@apple.com>
</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->abort();
</del><ins>+ m_private->resetParserState();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void SourceBuffer::abort(ExceptionCode& 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->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) && USE(AVFOUNDATION)
</span><span class="cx">
</span><span class="cx"> #include "SourceBufferPrivate.h"
</span><ins>+#include <dispatch/group.h>
</ins><span class="cx"> #include <dispatch/semaphore.h>
</span><span class="cx"> #include <wtf/Deque.h>
</span><span class="cx"> #include <wtf/HashMap.h>
</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<SourceBufferPrivateAVFObjCErrorClient*> m_errorClients;
</span><span class="cx">
</span><span class="cx"> WeakPtrFactory<SourceBufferPrivateAVFObjC> m_weakFactory;
</span><ins>+ WeakPtrFactory<SourceBufferPrivateAVFObjC> m_appendWeakFactory;
</ins><span class="cx">
</span><span class="cx"> RetainPtr<AVStreamDataParser> m_parser;
</span><span class="cx"> RetainPtr<AVAsset> m_asset;
</span><span class="lines">@@ -148,6 +151,7 @@
</span><span class="cx"> RetainPtr<WebAVSampleBufferErrorListener> m_errorListener;
</span><span class="cx"> RetainPtr<NSError> m_hdcpError;
</span><span class="cx"> OSObjectPtr<dispatch_semaphore_t> m_hasSessionSemaphore;
</span><ins>+ OSObjectPtr<dispatch_group_t> 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<WebCore::SourceBufferPrivateAVFObjC> _parent;
</span><span class="cx"> AVStreamDataParser* _parser;
</span><span class="cx"> }
</span><ins>+@property (assign) WeakPtr<WebCore::SourceBufferPrivateAVFObjC> parent;
</ins><span class="cx"> - (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr<WebCore::SourceBufferPrivateAVFObjC>)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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> RetainPtr<AVAsset*> protectedAsset = asset;
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());
</del><ins>+ callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> RetainPtr<AVAsset*> protectedAsset = asset;
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());
</del><ins>+ callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> RetainPtr<NSError> protectedError = error;
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedError = WTFMove(protectedError)] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didFailToParseStreamDataWithError(protectedError.get());
</del><ins>+ callOnMainThread([parent = _parent, protectedError = WTFMove(protectedError)] {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> RetainPtr<CMSampleBufferRef> protectedSample = sample;
</span><span class="cx"> String mediaType = nsMediaType;
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags);
</del><ins>+ callOnMainThread([parent = _parent, protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> String mediaType = nsMediaType;
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), trackID, mediaType] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didReachEndOfTrackWithTrackID(trackID, mediaType);
</del><ins>+ callOnMainThread([parent = _parent, trackID, mediaType] {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> strongSelf = self;
- dispatch_sync(dispatch_get_main_queue(), [strongSelf, trackID]() {
- if (strongSelf->_parent)
- strongSelf->_parent->willProvideContentKeyRequestInitializationDataForTrackID(trackID);
</del><ins>+ dispatch_sync(dispatch_get_main_queue(), [parent = _parent, trackID]() {
+ if (parent)
+ parent->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<WebAVStreamDataParserListener> protectedSelf = self;
</del><span class="cx">
</span><span class="cx"> OSObjectPtr<dispatch_semaphore_t> hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0));
</span><del>- callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedInitData = RetainPtr<NSData>(initData), trackID, hasSessionSemaphore] {
- if (protectedSelf->_parent)
- protectedSelf->_parent->didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore);
</del><ins>+ callOnMainThread([parent = _parent, protectedInitData = RetainPtr<NSData>(initData), trackID, hasSessionSemaphore] {
+ if (parent)
+ parent->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, "SourceBufferPrivateAVFObjC::append(%p) - data:%p, length:%d", this, data, length);
</span><span class="cx">
</span><span class="cx"> RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]);
</span><del>- WeakPtr<SourceBufferPrivateAVFObjC> weakThis = createWeakPtr();
</del><ins>+ WeakPtr<SourceBufferPrivateAVFObjC> weakThis = m_appendWeakFactory.createWeakPtr();
</ins><span class="cx"> RetainPtr<AVStreamDataParser> parser = m_parser;
</span><span class="cx"> RetainPtr<WebAVStreamDataParserListener> 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->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->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 << 0
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+typedef NS_ENUM(NSUInteger, AVStreamDataParserStreamDataFlags) {
+ AVStreamDataParserStreamDataDiscontinuity = 1 << 0,
+};
+
</ins><span class="cx"> @interface AVStreamDataParser : NSObject
</span><span class="cx"> - (void)setDelegate:(nullable id<AVStreamDataParserOutputHandling>)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>