<!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>[172584] 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/172584">172584</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2014-08-14 08:13:03 -0700 (Thu, 14 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE] Altering the quality of a YouTube video will cause the video to distort and display an error message
https://bugs.webkit.org/show_bug.cgi?id=135931

Reviewed by Eric Carlson.

When removing samples from the TrackBuffer's sample map, also remove those samples from the
TrackBuffer's decode queue. Otherwise, removed samples may persist in the decode queue and
either break sync-sample dependencies or cause decoding artifacts.

Pull the code which removes samples from a track buffer into its own utility function, and
use this function both from removeCodedFrames(), and also when samples are removed due to
overlapping appends in sourceBufferPrivateDidReceiveSample(). In order to reference
TrackBuffers outside of SourceBuffer (and in the static removeSamplesFromTrackBuffer()
function), make TrackBuffer a public forward declaration.

* Modules/mediasource/SourceBuffer.cpp:
(WebCore::removeSamplesFromTrackBuffer):
(WebCore::SourceBuffer::removeCodedFrames):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
* Modules/mediasource/SourceBuffer.h:</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (172583 => 172584)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-14 13:10:37 UTC (rev 172583)
+++ trunk/Source/WebCore/ChangeLog        2014-08-14 15:13:03 UTC (rev 172584)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2014-08-14  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Altering the quality of a YouTube video will cause the video to distort and display an error message
+        https://bugs.webkit.org/show_bug.cgi?id=135931
+
+        Reviewed by Eric Carlson.
+
+        When removing samples from the TrackBuffer's sample map, also remove those samples from the
+        TrackBuffer's decode queue. Otherwise, removed samples may persist in the decode queue and
+        either break sync-sample dependencies or cause decoding artifacts.
+
+        Pull the code which removes samples from a track buffer into its own utility function, and
+        use this function both from removeCodedFrames(), and also when samples are removed due to
+        overlapping appends in sourceBufferPrivateDidReceiveSample(). In order to reference
+        TrackBuffers outside of SourceBuffer (and in the static removeSamplesFromTrackBuffer()
+        function), make TrackBuffer a public forward declaration.
+
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::removeSamplesFromTrackBuffer):
+        (WebCore::SourceBuffer::removeCodedFrames):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
+        * Modules/mediasource/SourceBuffer.h:
+
</ins><span class="cx"> 2014-08-14  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ImageBufferDataCairo.h is missing header guards
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (172583 => 172584)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-08-14 13:10:37 UTC (rev 172583)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2014-08-14 15:13:03 UTC (rev 172584)
</span><span class="lines">@@ -527,6 +527,27 @@
</span><span class="cx">     return a.second-&gt;decodeTime() &lt; b.second-&gt;decodeTime();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static PassRefPtr&lt;TimeRanges&gt; removeSamplesFromTrackBuffer(const DecodeOrderSampleMap::MapType&amp; samples, SourceBuffer::TrackBuffer&amp; trackBuffer)
+{
+    RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
+    MediaTime microsecond(1, 1000000);
+    for (auto sampleIt : samples) {
+        const DecodeOrderSampleMap::KeyType&amp; decodeKey = sampleIt.first;
+        RefPtr&lt;MediaSample&gt;&amp; sample = sampleIt.second;
+
+        // Remove the erased samples from the TrackBuffer sample map.
+        trackBuffer.samples.removeSample(sample.get());
+
+        // Also remove the erased samples from the TrackBuffer decodeQueue.
+        trackBuffer.decodeQueue.erase(decodeKey);
+
+        double startTime = sample-&gt;presentationTime().toDouble();
+        double endTime = startTime + (sample-&gt;duration() + microsecond).toDouble();
+        erasedRanges-&gt;add(startTime, endTime);
+    }
+    return erasedRanges.release();
+}
+
</ins><span class="cx"> void SourceBuffer::removeCodedFrames(const MediaTime&amp; start, const MediaTime&amp; end)
</span><span class="cx"> {
</span><span class="cx">     LOG(MediaSource, &quot;SourceBuffer::removeCodedFrames(%p) - start(%s), end(%s)&quot;, this, toString(start).utf8().data(), toString(end).utf8().data());
</span><span class="lines">@@ -569,17 +590,8 @@
</span><span class="cx">         DecodeOrderSampleMap::iterator removeDecodeStart = trackBuffer.samples.decodeOrder().findSampleWithDecodeKey(decodeKey);
</span><span class="cx"> 
</span><span class="cx">         DecodeOrderSampleMap::MapType erasedSamples(removeDecodeStart, removeDecodeEnd);
</span><ins>+        RefPtr&lt;TimeRanges&gt; erasedRanges = removeSamplesFromTrackBuffer(erasedSamples, trackBuffer);
</ins><span class="cx"> 
</span><del>-        RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
-        MediaTime microsecond(1, 1000000);
-        for (auto erasedIt : erasedSamples) {
-            RefPtr&lt;MediaSample&gt;&amp; sample = erasedIt.second;
-            trackBuffer.samples.removeSample(sample.get());
-            double startTime = sample-&gt;presentationTime().toDouble();
-            double endTime = startTime + (sample-&gt;duration() + microsecond).toDouble();
-            erasedRanges-&gt;add(startTime, endTime);
-        }
-
</del><span class="cx">         // Only force the TrackBuffer to re-enqueue if the removed ranges overlap with enqueued and possibly
</span><span class="cx">         // not yet displayed samples.
</span><span class="cx">         PlatformTimeRanges possiblyEnqueuedRanges(currentMediaTime, trackBuffer.lastEnqueuedPresentationTime);
</span><span class="lines">@@ -1186,15 +1198,11 @@
</span><span class="cx">             auto nextSyncIter = trackBuffer.samples.decodeOrder().findSyncSampleAfterDecodeIterator(lastDecodeIter);
</span><span class="cx">             dependentSamples.insert(firstDecodeIter, nextSyncIter);
</span><span class="cx"> 
</span><del>-
-            RefPtr&lt;TimeRanges&gt; erasedRanges = TimeRanges::create();
-            for (auto&amp; samplePair : dependentSamples) {
-                MediaTime startTime = samplePair.second-&gt;presentationTime();
-                MediaTime endTime = startTime + samplePair.second-&gt;duration() + microsecond;
-                erasedRanges-&gt;add(startTime.toDouble(), endTime.toDouble());
</del><ins>+            RefPtr&lt;TimeRanges&gt; erasedRanges = removeSamplesFromTrackBuffer(dependentSamples, trackBuffer);
+#if !LOG_DISABLED
+            for (auto&amp; samplePair : dependentSamples)
</ins><span class="cx">                 LOG(MediaSource, &quot;SourceBuffer::sourceBufferPrivateDidReceiveSample(%p) - removing sample(%s)&quot;, this, toString(*samplePair.second).utf8().data());
</span><del>-                trackBuffer.samples.removeSample(samplePair.second.get());
-            }
</del><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx">             // Only force the TrackBuffer to re-enqueue if the removed ranges overlap with enqueued and possibly
</span><span class="cx">             // not yet displayed samples.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (172583 => 172584)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-08-14 13:10:37 UTC (rev 172583)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2014-08-14 15:13:03 UTC (rev 172584)
</span><span class="lines">@@ -103,6 +103,8 @@
</span><span class="cx">     using RefCounted&lt;SourceBuffer&gt;::ref;
</span><span class="cx">     using RefCounted&lt;SourceBuffer&gt;::deref;
</span><span class="cx"> 
</span><ins>+    struct TrackBuffer;
+
</ins><span class="cx"> protected:
</span><span class="cx">     // EventTarget interface
</span><span class="cx">     virtual void refEventTarget() override { ref(); }
</span><span class="lines">@@ -149,7 +151,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool validateInitializationSegment(const InitializationSegment&amp;);
</span><span class="cx"> 
</span><del>-    struct TrackBuffer;
</del><span class="cx">     void reenqueueMediaForTime(TrackBuffer&amp;, AtomicString trackID, const MediaTime&amp;);
</span><span class="cx">     void provideMediaData(TrackBuffer&amp;, AtomicString trackID);
</span><span class="cx">     void didDropSample();
</span></span></pre>
</div>
</div>

</body>
</html>