<!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>[168974] trunk/Source/WebCore</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>[MSE] Crash at  WebCore::SourceBuffer::~SourceBuffer + 110
https://bugs.webkit.org/show_bug.cgi?id=132973

Reviewed by Eric Carlson.

Change SourceBuffer::m_private into a Ref&lt;&gt;, and add an assertion to
SourceBufferPrivateAVFObjC's destructor if its client has not been cleared.

Eliminate unnecessary churn in MediaSourcePrivateAVFObjC by having the predicate
functor take bare pointers, rather than a PassRefPtr.

The underlying problem seems to be in WebAVStreamDataParserListener. RefPtrs were
being created off the main thread to a non-thread safe ref counted class. In some
situations, this would result in double decrementing the ref, which would cause an
early destruction of the underlying object. Instead replace these RefPtr strong
pointers with explicit weak ones. Ensure the parser and its delegate are not freed
before the append operation completes by passing strong pointers into the async
append operation lambda.

There were a few places where we weren't null checking m_mediaSource before using it,
and at least one place where we weren't clearing m_mediaSource.

* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::SourceBuffer): Use Ref instead of RefPtr.
(WebCore::SourceBuffer::appendBufferTimerFired): Ditto.
* Modules/mediasource/SourceBuffer.h:
* platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
(WebCore::MediaSourcePrivateAVFObjCHasAudio): Take a bare pointer, instead of a PassRefPtr.
(WebCore::MediaSourcePrivateAVFObjCHasVideo): Ditto.
* platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
(WebCore::MediaSourcePrivateAVFObjC::removeSourceBuffer): Clear the back pointer when removing a buffer.
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(-[WebAVStreamDataParserListener initWithParser:parent:WebCore::]): Use WeakPtr instead of RefPtr.
(-[WebAVStreamDataParserListener invalidate]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]): Ditto.
(-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]): Ditto.
(WebCore::SourceBufferPrivateAVFObjC::~SourceBufferPrivateAVFObjC):
(WebCore::SourceBufferPrivateAVFObjC::append): Ditto.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBuffercpp">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBufferh">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/ChangeLog        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2014-05-16  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Crash at  WebCore::SourceBuffer::~SourceBuffer + 110
+        https://bugs.webkit.org/show_bug.cgi?id=132973
+
+        Reviewed by Eric Carlson.
+
+        Change SourceBuffer::m_private into a Ref&lt;&gt;, and add an assertion to
+        SourceBufferPrivateAVFObjC's destructor if its client has not been cleared.
+
+        Eliminate unnecessary churn in MediaSourcePrivateAVFObjC by having the predicate
+        functor take bare pointers, rather than a PassRefPtr.
+
+        The underlying problem seems to be in WebAVStreamDataParserListener. RefPtrs were
+        being created off the main thread to a non-thread safe ref counted class. In some
+        situations, this would result in double decrementing the ref, which would cause an
+        early destruction of the underlying object. Instead replace these RefPtr strong
+        pointers with explicit weak ones. Ensure the parser and its delegate are not freed
+        before the append operation completes by passing strong pointers into the async
+        append operation lambda.
+
+        There were a few places where we weren't null checking m_mediaSource before using it,
+        and at least one place where we weren't clearing m_mediaSource.
+
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::SourceBuffer): Use Ref instead of RefPtr.
+        (WebCore::SourceBuffer::appendBufferTimerFired): Ditto.
+        * Modules/mediasource/SourceBuffer.h:
+        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
+        (WebCore::MediaSourcePrivateAVFObjCHasAudio): Take a bare pointer, instead of a PassRefPtr.
+        (WebCore::MediaSourcePrivateAVFObjCHasVideo): Ditto.
+        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
+        (WebCore::MediaSourcePrivateAVFObjC::removeSourceBuffer): Clear the back pointer when removing a buffer.
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (-[WebAVStreamDataParserListener initWithParser:parent:WebCore::]): Use WeakPtr instead of RefPtr.
+        (-[WebAVStreamDataParserListener invalidate]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]): Ditto.
+        (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]): Ditto.
+        (WebCore::SourceBufferPrivateAVFObjC::~SourceBufferPrivateAVFObjC):
+        (WebCore::SourceBufferPrivateAVFObjC::append): Ditto.
+
</ins><span class="cx"> 2014-05-16  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Subpixel rendering: Push named flows in region to device pixel when painting.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -107,7 +107,6 @@
</span><span class="cx">     , m_pendingRemoveEnd(MediaTime::invalidTime())
</span><span class="cx">     , m_removeTimer(this, &amp;SourceBuffer::removeTimerFired)
</span><span class="cx"> {
</span><del>-    ASSERT(m_private);
</del><span class="cx">     ASSERT(m_source);
</span><span class="cx"> 
</span><span class="cx">     m_private-&gt;setClient(this);
</span><span class="lines">@@ -474,7 +473,7 @@
</span><span class="cx"> 
</span><span class="cx">     // 1. Loop Top: If the input buffer is empty, then jump to the need more data step below.
</span><span class="cx">     if (!m_pendingAppendData.size()) {
</span><del>-        sourceBufferPrivateAppendComplete(m_private.get(), AppendSucceeded);
</del><ins>+        sourceBufferPrivateAppendComplete(&amp;m_private.get(), AppendSucceeded);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -156,7 +156,7 @@
</span><span class="cx">     void removeTimerFired(Timer&lt;SourceBuffer&gt;*);
</span><span class="cx">     void removeCodedFrames(const MediaTime&amp; start, const MediaTime&amp; end);
</span><span class="cx"> 
</span><del>-    RefPtr&lt;SourceBufferPrivate&gt; m_private;
</del><ins>+    Ref&lt;SourceBufferPrivate&gt; m_private;
</ins><span class="cx">     MediaSource* m_source;
</span><span class="cx">     GenericEventQueue m_asyncEventQueue;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx">         m_activeSourceBuffers.remove(pos);
</span><span class="cx"> 
</span><span class="cx">     pos = m_sourceBuffers.find(buffer);
</span><ins>+    m_sourceBuffers[pos]-&gt;clearMediaSource();
</ins><span class="cx">     m_sourceBuffers.remove(pos);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -157,9 +158,8 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-static bool MediaSourcePrivateAVFObjCHasAudio(PassRefPtr&lt;SourceBufferPrivateAVFObjC&gt; prpSourceBuffer)
</del><ins>+static bool MediaSourcePrivateAVFObjCHasAudio(SourceBufferPrivateAVFObjC* sourceBuffer)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;SourceBufferPrivateAVFObjC&gt; sourceBuffer = prpSourceBuffer;
</del><span class="cx">     return sourceBuffer-&gt;hasAudio();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -168,9 +168,8 @@
</span><span class="cx">     return std::any_of(m_activeSourceBuffers.begin(), m_activeSourceBuffers.end(), MediaSourcePrivateAVFObjCHasAudio);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool MediaSourcePrivateAVFObjCHasVideo(PassRefPtr&lt;SourceBufferPrivateAVFObjC&gt; prpSourceBuffer)
</del><ins>+static bool MediaSourcePrivateAVFObjCHasVideo(SourceBufferPrivateAVFObjC* sourceBuffer)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;SourceBufferPrivateAVFObjC&gt; sourceBuffer = prpSourceBuffer;
</del><span class="cx">     return sourceBuffer-&gt;hasVideo();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><ins>+#include &lt;wtf/WeakPtr.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/AtomicString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> OBJC_CLASS AVAsset;
</span><span class="lines">@@ -113,9 +114,13 @@
</span><span class="cx">     void destroyParser();
</span><span class="cx">     void destroyRenderers();
</span><span class="cx"> 
</span><ins>+    WeakPtr&lt;SourceBufferPrivateAVFObjC&gt; createWeakPtr() { return m_weakFactory.createWeakPtr(); }
+
</ins><span class="cx">     Vector&lt;RefPtr&lt;VideoTrackPrivateMediaSourceAVFObjC&gt;&gt; m_videoTracks;
</span><span class="cx">     Vector&lt;RefPtr&lt;AudioTrackPrivateMediaSourceAVFObjC&gt;&gt; m_audioTracks;
</span><span class="cx"> 
</span><ins>+    WeakPtrFactory&lt;SourceBufferPrivateAVFObjC&gt; m_weakFactory;
+
</ins><span class="cx">     RetainPtr&lt;AVStreamDataParser&gt; m_parser;
</span><span class="cx">     RetainPtr&lt;AVAsset&gt; m_asset;
</span><span class="cx">     RetainPtr&lt;AVSampleBufferDisplayLayer&gt; m_displayLayer;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (168973 => 168974)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2014-05-16 19:01:57 UTC (rev 168973)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2014-05-16 19:45:15 UTC (rev 168974)
</span><span class="lines">@@ -153,14 +153,14 @@
</span><span class="cx"> #pragma mark WebAVStreamDataParserListener
</span><span class="cx"> 
</span><span class="cx"> @interface WebAVStreamDataParserListener : NSObject {
</span><del>-    WebCore::SourceBufferPrivateAVFObjC* _parent;
</del><ins>+    WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; _parent;
</ins><span class="cx">     AVStreamDataParser* _parser;
</span><span class="cx"> }
</span><del>-- (id)initWithParser:(AVStreamDataParser*)parser parent:(WebCore::SourceBufferPrivateAVFObjC*)parent;
</del><ins>+- (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt;)parent;
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WebAVStreamDataParserListener
</span><del>-- (id)initWithParser:(AVStreamDataParser*)parser parent:(WebCore::SourceBufferPrivateAVFObjC*)parent
</del><ins>+- (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt;)parent
</ins><span class="cx"> {
</span><span class="cx">     self = [super init];
</span><span class="cx">     if (!self)
</span><span class="lines">@@ -182,7 +182,6 @@
</span><span class="cx"> - (void)invalidate
</span><span class="cx"> {
</span><span class="cx">     [_parser setDelegate:nil];
</span><del>-    _parent = nullptr;
</del><span class="cx">     _parser = nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -192,13 +191,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVAsset*&gt; strongAsset = asset;
</span><del>-    callOnMainThread([strongParent, strongAsset] {
-        strongParent-&gt;didParseStreamDataAsAsset(strongAsset.get());
</del><ins>+    callOnMainThread([strongSelf, strongAsset] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didParseStreamDataAsAsset(strongAsset.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -209,13 +207,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;AVAsset*&gt; strongAsset = asset;
</span><del>-    callOnMainThread([strongParent, strongAsset] {
-        strongParent-&gt;didParseStreamDataAsAsset(strongAsset.get());
</del><ins>+    callOnMainThread([strongSelf, strongAsset] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didParseStreamDataAsAsset(strongAsset.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -225,13 +222,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSError&gt; strongError = error;
</span><del>-    callOnMainThread([strongParent, strongError] {
-        strongParent-&gt;didFailToParseStreamDataWithError(strongError.get());
</del><ins>+    callOnMainThread([strongSelf, strongError] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didFailToParseStreamDataWithError(strongError.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -241,14 +237,13 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CMSampleBufferRef&gt; strongSample = sample;
</span><span class="cx">     String mediaType = nsMediaType;
</span><del>-    callOnMainThread([strongParent, strongSample, trackID, mediaType, flags] {
-        strongParent-&gt;didProvideMediaDataForTrackID(trackID, strongSample.get(), mediaType, flags);
</del><ins>+    callOnMainThread([strongSelf, strongSample, trackID, mediaType, flags] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didProvideMediaDataForTrackID(trackID, strongSample.get(), mediaType, flags);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -258,13 +253,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     String mediaType = nsMediaType;
</span><del>-    callOnMainThread([strongParent, trackID, mediaType] {
-        strongParent-&gt;didReachEndOfTrackWithTrackID(trackID, mediaType);
</del><ins>+    callOnMainThread([strongSelf, trackID, mediaType] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didReachEndOfTrackWithTrackID(trackID, mediaType);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -274,13 +268,12 @@
</span><span class="cx">     UNUSED_PARAM(streamDataParser);
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><del>-    RefPtr&lt;WebCore::SourceBufferPrivateAVFObjC&gt; strongParent = _parent;
-    if (!strongParent)
-        return;
</del><ins>+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSData&gt; strongData = initData;
</span><del>-    callOnMainThread([strongParent, strongData, trackID] {
-        strongParent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID);
</del><ins>+    callOnMainThread([strongSelf, strongData, trackID] {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> @end
</span><span class="lines">@@ -386,8 +379,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC(MediaSourcePrivateAVFObjC* parent)
</span><del>-    : m_parser(adoptNS([[getAVStreamDataParserClass() alloc] init]))
-    , m_delegate(adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:this]))
</del><ins>+    : m_weakFactory(this)
+    , m_parser(adoptNS([[getAVStreamDataParserClass() alloc] init]))
+    , m_delegate(adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()]))
</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">@@ -398,6 +392,7 @@
</span><span class="cx"> 
</span><span class="cx"> SourceBufferPrivateAVFObjC::~SourceBufferPrivateAVFObjC()
</span><span class="cx"> {
</span><ins>+    ASSERT(!m_client);
</ins><span class="cx">     destroyParser();
</span><span class="cx">     destroyRenderers();
</span><span class="cx"> }
</span><span class="lines">@@ -469,7 +464,8 @@
</span><span class="cx">         if (formatSize != m_cachedSize) {
</span><span class="cx">             LOG(Media, &quot;SourceBufferPrivateAVFObjC::processCodedFrame(%p) - size change detected: {width=%lf, height=%lf&quot;, formatSize.width(), formatSize.height());
</span><span class="cx">             m_cachedSize = formatSize;
</span><del>-            m_mediaSource-&gt;player()-&gt;sizeChanged();
</del><ins>+            if (m_mediaSource)
+                m_mediaSource-&gt;player()-&gt;sizeChanged();
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     if (m_client)
</span><span class="lines">@@ -487,6 +483,9 @@
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(NSData* initData, int trackID)
</span><span class="cx"> {
</span><ins>+    if (!m_mediaSource)
+        return;
+
</ins><span class="cx">     UNUSED_PARAM(trackID);
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><span class="cx">     LOG(Media, &quot;SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(%p) - track:%d&quot;, this, trackID);
</span><span class="lines">@@ -519,15 +518,19 @@
</span><span class="cx">     LOG(Media, &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>-    RefPtr&lt;SourceBufferPrivateAVFObjC&gt; strongThis = this;
</del><ins>+    WeakPtr&lt;SourceBufferPrivateAVFObjC&gt; weakThis = createWeakPtr();
+    RetainPtr&lt;AVStreamDataParser&gt; parser = m_parser;
+    RetainPtr&lt;WebAVStreamDataParserListener&gt; delegate = m_delegate;
</ins><span class="cx"> 
</span><span class="cx">     m_parsingSucceeded = true;
</span><span class="cx"> 
</span><del>-    dispatch_async(globalDataParserQueue(), [nsData, strongThis] {
-        [strongThis-&gt;m_parser appendStreamData:nsData.get()];
</del><ins>+    dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate] {
</ins><span class="cx"> 
</span><del>-        callOnMainThread([strongThis] {
-            strongThis-&gt;appendCompleted();
</del><ins>+        [parser appendStreamData:nsData.get()];
+
+        callOnMainThread([weakThis] {
+            if (weakThis)
+                weakThis-&gt;appendCompleted();
</ins><span class="cx">         });
</span><span class="cx">     });
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>