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

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

<h3>Log Message</h3>
<pre>[MSE] Add support for VideoPlaybackMetrics.
https://bugs.webkit.org/show_bug.cgi?id=125380

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/media-source/media-source-video-playback-quality.html

Add a new object type VideoPlaybackQuality to be returned by
HTMLMediaElement.getVideoPlaybackQuality().

HTMLMediaElements must separately track a droppedVideoFrame count, as
certain operations on SourceBuffer will drop incoming frames, which must
be accounted for. Reset this count when the media engine changes, which is
indicitive of a new media load requset starting.

Add the new VideoPlaybackQuality class:
* Modules/mediasource/VideoPlaybackQuality.cpp: Added.
(WebCore::VideoPlaybackQuality::create):
(WebCore::VideoPlaybackQuality::VideoPlaybackQuality):
* Modules/mediasource/VideoPlaybackQuality.h: Added.
(WebCore::VideoPlaybackQuality::creationTime):
(WebCore::VideoPlaybackQuality::totalVideoFrames):
(WebCore::VideoPlaybackQuality::droppedVideoFrames):
(WebCore::VideoPlaybackQuality::corruptedVideoFrames):
(WebCore::VideoPlaybackQuality::totalFrameDelay):
* Modules/mediasource/VideoPlaybackQuality.idl: Added.

Add support for the new class to HTMLMediaElement:
* html/HTMLMediaElement.cpp:
(HTMLMediaElement::shouldUseVideoPluginProxy):
(HTMLMediaElement::getVideoPlaybackQuality):
* html/HTMLMediaElement.h:
* html/HTMLMediaElement.idl:

Report the video quality metrics from the MediaPlayer:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::totalVideoFrames):
(WebCore::MediaPlayer::droppedVideoFrames):
(WebCore::MediaPlayer::corruptedVideoFrames):
(WebCore::MediaPlayer::totalFrameDelay):
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::totalVideoFrames):
(WebCore::MediaPlayerPrivateInterface::droppedVideoFrames):
(WebCore::MediaPlayerPrivateInterface::corruptedVideoFrames):
(WebCore::MediaPlayerPrivateInterface::totalFrameDelay):

Correctly report the dropped frame count:
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::TrackBuffer::TrackBuffer): needsRandomAccessFlag defaults to true.
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample): Check the sync status of the incoming sample.
(WebCore::SourceBuffer::didDropSample): Notify the media element of a dropped frame.
* Modules/mediasource/SourceBuffer.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(HTMLMediaElement::mediaPlayerEngineUpdated): Reset m_droppedFrameCount.
(HTMLMediaElement::getVideoPlaybackQuality): Return a new VideoPlaybackQuality object.
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::incrementDroppedFrameCount): Simple incrementer.
* platform/MediaSample.h:
(WebCore::MediaSample::isSync): Convenience function.
(WebCore::MediaSample::isNonDisplaying): Ditto.

Add support in the AVFoundation MediaSource Engine:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::totalVideoFrames):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::droppedVideoFrames):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::corruptedVideoFrames):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::totalFrameDelay):

Add support in the Mock MediaSource Engine:
* platform/mock/mediasource/MockBox.h:
* platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
(WebCore::MockMediaPlayerMediaSource::totalVideoFrames): Simple accessor.
(WebCore::MockMediaPlayerMediaSource::droppedVideoFrames): Ditto.
(WebCore::MockMediaPlayerMediaSource::corruptedVideoFrames): Ditto.
(WebCore::MockMediaPlayerMediaSource::totalFrameDelay): Ditto.
* platform/mock/mediasource/MockMediaPlayerMediaSource.h:
* platform/mock/mediasource/MockMediaSourcePrivate.cpp:
(WebCore::MockMediaSourcePrivate::MockMediaSourcePrivate):
* platform/mock/mediasource/MockMediaSourcePrivate.h:
* platform/mock/mediasource/MockSourceBufferPrivate.cpp:
(WebCore::MockSourceBufferPrivate::enqueueSample): Increment the frame counts based on
    the incoming sample.
* platform/mock/mediasource/MockSourceBufferPrivate.h:

Add the new files to the project:
* bindings/gobject/GNUmakefile.am:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* GNUMakefile.list.am:
* CMakeLists.txt:

LayoutTests:

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcecanplaythroughhtml">trunk/LayoutTests/media/media-source/media-source-canplaythrough.html</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourceplayhtml">trunk/LayoutTests/media/media-source/media-source-play.html</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemockmediasourcejs">trunk/LayoutTests/media/media-source/mock-media-source.js</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreGNUmakefilelistam">trunk/Source/WebCore/GNUmakefile.list.am</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBuffercpp">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceSourceBufferh">trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsgobjectGNUmakefileam">trunk/Source/WebCore/bindings/gobject/GNUmakefile.am</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementh">trunk/Source/WebCore/html/HTMLMediaElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementidl">trunk/Source/WebCore/html/HTMLMediaElement.idl</a></li>
<li><a href="#trunkSourceWebCoreplatformMediaSampleh">trunk/Source/WebCore/platform/MediaSample.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayercpp">trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerh">trunk/Source/WebCore/platform/graphics/MediaPlayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh">trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockBoxh">trunk/Source/WebCore/platform/mock/mediasource/MockBox.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourcecpp">trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourceh">trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivatecpp">trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivateh">trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp">trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh">trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcevideoplaybackqualityexpectedtxt">trunk/LayoutTests/media/media-source/media-source-video-playback-quality-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamediasourcemediasourcevideoplaybackqualityhtml">trunk/LayoutTests/media/media-source/media-source-video-playback-quality.html</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceVideoPlaybackQualitycpp">trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceVideoPlaybackQualityh">trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceVideoPlaybackQualityidl">trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/LayoutTests/ChangeLog        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2013-12-09  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Add support for VideoPlaybackMetrics.
+        https://bugs.webkit.org/show_bug.cgi?id=125380
+
+        Reviewed by Eric Carlson.
+
+        * media/media-source/media-source-video-playback-quality-expected.txt: Added.
+        * media/media-source/media-source-video-playback-quality.html: Added.
+        * media/media-source/mock-media-source.js:
+        (var):
+
</ins><span class="cx"> 2013-12-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement Document.cloneNode()
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcecanplaythroughhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/media-source/media-source-canplaythrough.html (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-canplaythrough.html        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/LayoutTests/media/media-source/media-source-canplaythrough.html        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx">     function sourceUpdated() {
</span><span class="cx">         source.activeSourceBuffers.length;
</span><span class="cx">         if (nextRequest &lt; totalLength) {
</span><del>-            sourceBuffer.appendBuffer(makeASample(nextRequest, nextRequest, 1, 1, 0));
</del><ins>+            sourceBuffer.appendBuffer(makeASample(nextRequest, nextRequest, 1, 1, SAMPLE_FLAG.SYNC));
</ins><span class="cx">             ++nextRequest;
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourceplayhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/media-source/media-source-play.html (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-play.html        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/LayoutTests/media/media-source/media-source-play.html        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function loadSamples() {
</span><del>-        sample = makeASample(0, 0, 10, 1, 0);
</del><ins>+        sample = makeASample(0, 0, 10, 1, SAMPLE_FLAG.SYNC);
</ins><span class="cx">         waitForEventOn(sourceBuffer, 'updateend', play, false, true);
</span><span class="cx">         run('sourceBuffer.appendBuffer(sample)');
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcevideoplaybackqualityexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-video-playback-quality-expected.txt (0 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-video-playback-quality-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-video-playback-quality-expected.txt        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;))
+RUN(sourceBuffer.appendBuffer(initSegment))
+EVENT(updateend)
+Test that beginning a buffer with a non-sync sample results in that sample being dropped.
+RUN(sourceBuffer.appendBuffer(samples))
+EVENT(updateend)
+RUN(quality = video.getVideoPlaybackQuality())
+EXPECTED (quality.totalVideoFrames == '1') OK
+EXPECTED (quality.corruptedVideoFrames == '0') OK
+EXPECTED (quality.droppedVideoFrames == '1') OK
+EXPECTED (quality.totalFrameDelay == '0') OK
+RUN(sourceBuffer.appendBuffer(samples))
+EVENT(updateend)
+RUN(quality = video.getVideoPlaybackQuality())
+EXPECTED (quality.totalVideoFrames == '8') OK
+EXPECTED (quality.corruptedVideoFrames == '1') OK
+EXPECTED (quality.droppedVideoFrames == '2') OK
+EXPECTED (quality.totalFrameDelay == '3') OK
+END OF TEST
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemediasourcevideoplaybackqualityhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/media-source/media-source-video-playback-quality.html (0 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/media-source-video-playback-quality.html                                (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-video-playback-quality.html        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;title&gt;mock-media-source&lt;/title&gt;
+    &lt;script src=&quot;mock-media-source.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;../video-test.js&quot;&gt;&lt;/script&gt;
+    &lt;script&gt;
+    var source;
+    var sourceBuffer;
+    var initSegment;
+    var samples;
+    var quality;
+
+    if (window.internals)
+        internals.initializeMockMediaSource();
+
+    function runTest()
+    {
+        findMediaElement();
+
+        source = new MediaSource();
+        waitForEventOn(source, 'sourceopen', sourceOpen);
+        run('video.src = URL.createObjectURL(source)');
+    }
+
+    function sourceOpen()
+    {
+        run('sourceBuffer = source.addSourceBuffer(&quot;video/mock; codecs=mock&quot;)');
+        waitForEventOn(sourceBuffer, 'updateend', loadSample, false, true);
+        initSegment = makeAInit(8, [makeATrack(1, 'mock', TRACK_KIND.VIDEO)]);
+        run('sourceBuffer.appendBuffer(initSegment)');
+    }
+
+    function loadSample()
+    {
+        samples = concatenateSamples([makeASample(0, 0, 1, 1, SAMPLE_FLAG.NONE)]);
+        waitForEventOn(sourceBuffer, 'updateend', loadMoreSamples, false, true);
+        consoleWrite('Test that beginning a buffer with a non-sync sample results in that sample being dropped.')
+        run('sourceBuffer.appendBuffer(samples)');
+    }
+
+    function loadMoreSamples()
+    {
+        run('quality = video.getVideoPlaybackQuality()');
+        testExpected('quality.totalVideoFrames', 1);
+        testExpected('quality.corruptedVideoFrames', 0);
+        testExpected('quality.droppedVideoFrames', 1);
+        testExpected('quality.totalFrameDelay', 0);
+
+        samples = concatenateSamples([
+            makeASample(0, 0, 1, 1, SAMPLE_FLAG.SYNC),
+            makeASample(1, 1, 1, 1, SAMPLE_FLAG.CORRUPTED),
+            makeASample(2, 2, 1, 1, SAMPLE_FLAG.DROPPED),
+            makeASample(4, 4, 1, 1, SAMPLE_FLAG.DELAYED),
+            makeASample(5, 5, 1, 1, SAMPLE_FLAG.DELAYED),
+            makeASample(6, 6, 1, 1, SAMPLE_FLAG.DELAYED),
+            makeASample(7, 7, 1, 1, SAMPLE_FLAG.NONE),
+        ]);
+        waitForEventOn(sourceBuffer, 'updateend', samplesAdded, false, true);
+        run('sourceBuffer.appendBuffer(samples)');
+    }
+
+    function samplesAdded()
+    {
+        run('quality = video.getVideoPlaybackQuality()');
+        testExpected('quality.totalVideoFrames', 8);
+        testExpected('quality.corruptedVideoFrames', 1);
+        testExpected('quality.droppedVideoFrames', 2);
+        testExpected('quality.totalFrameDelay', 3);
+        endTest();
+    }
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;video&gt;&lt;/video&gt;
+&lt;/body&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsmediamediasourcemockmediasourcejs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/media-source/mock-media-source.js (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/media-source/mock-media-source.js        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/LayoutTests/media/media-source/mock-media-source.js        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -11,6 +11,9 @@
</span><span class="cx"> var SAMPLE_FLAG = {
</span><span class="cx">     NONE: 0,
</span><span class="cx">     SYNC: 1 &lt;&lt; 0,
</span><ins>+    CORRUPTED: 1 &lt;&lt; 1,
+    DROPPED: 1 &lt;&lt; 2,
+    DELAYED: 1 &lt;&lt; 3,
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> function makeASample(presentationTime, decodeTime, duration, trackID, flags) {
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/CMakeLists.txt        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx">     Modules/mediasource/MediaSource.idl
</span><span class="cx">     Modules/mediasource/SourceBuffer.idl
</span><span class="cx">     Modules/mediasource/SourceBufferList.idl
</span><ins>+    Modules/mediasource/VideoPlaybackQuality.idl
</ins><span class="cx"> 
</span><span class="cx">     Modules/mediastream/AllAudioCapabilities.idl
</span><span class="cx">     Modules/mediastream/AllVideoCapabilities.idl
</span><span class="lines">@@ -829,6 +830,7 @@
</span><span class="cx">     Modules/mediasource/MediaSourceRegistry.cpp
</span><span class="cx">     Modules/mediasource/SourceBuffer.cpp
</span><span class="cx">     Modules/mediasource/SourceBufferList.cpp
</span><ins>+    Modules/mediasource/VideoPlaybackQuality.cpp
</ins><span class="cx"> 
</span><span class="cx">     Modules/mediastream/AudioStreamTrack.cpp
</span><span class="cx">     Modules/mediastream/CapabilityRange.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/ChangeLog        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -1,3 +1,99 @@
</span><ins>+2013-12-09  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE] Add support for VideoPlaybackMetrics.
+        https://bugs.webkit.org/show_bug.cgi?id=125380
+
+        Reviewed by Eric Carlson.
+
+        Test: media/media-source/media-source-video-playback-quality.html
+
+        Add a new object type VideoPlaybackQuality to be returned by
+        HTMLMediaElement.getVideoPlaybackQuality().
+
+        HTMLMediaElements must separately track a droppedVideoFrame count, as
+        certain operations on SourceBuffer will drop incoming frames, which must
+        be accounted for. Reset this count when the media engine changes, which is
+        indicitive of a new media load requset starting.
+
+        Add the new VideoPlaybackQuality class:
+        * Modules/mediasource/VideoPlaybackQuality.cpp: Added.
+        (WebCore::VideoPlaybackQuality::create):
+        (WebCore::VideoPlaybackQuality::VideoPlaybackQuality):
+        * Modules/mediasource/VideoPlaybackQuality.h: Added.
+        (WebCore::VideoPlaybackQuality::creationTime):
+        (WebCore::VideoPlaybackQuality::totalVideoFrames):
+        (WebCore::VideoPlaybackQuality::droppedVideoFrames):
+        (WebCore::VideoPlaybackQuality::corruptedVideoFrames):
+        (WebCore::VideoPlaybackQuality::totalFrameDelay):
+        * Modules/mediasource/VideoPlaybackQuality.idl: Added.
+
+        Add support for the new class to HTMLMediaElement:
+        * html/HTMLMediaElement.cpp:
+        (HTMLMediaElement::shouldUseVideoPluginProxy):
+        (HTMLMediaElement::getVideoPlaybackQuality):
+        * html/HTMLMediaElement.h:
+        * html/HTMLMediaElement.idl:
+
+        Report the video quality metrics from the MediaPlayer:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::totalVideoFrames):
+        (WebCore::MediaPlayer::droppedVideoFrames):
+        (WebCore::MediaPlayer::corruptedVideoFrames):
+        (WebCore::MediaPlayer::totalFrameDelay):
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::totalVideoFrames):
+        (WebCore::MediaPlayerPrivateInterface::droppedVideoFrames):
+        (WebCore::MediaPlayerPrivateInterface::corruptedVideoFrames):
+        (WebCore::MediaPlayerPrivateInterface::totalFrameDelay):
+
+        Correctly report the dropped frame count:
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::TrackBuffer::TrackBuffer): needsRandomAccessFlag defaults to true.
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample): Check the sync status of the incoming sample.
+        (WebCore::SourceBuffer::didDropSample): Notify the media element of a dropped frame.
+        * Modules/mediasource/SourceBuffer.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (HTMLMediaElement::mediaPlayerEngineUpdated): Reset m_droppedFrameCount.
+        (HTMLMediaElement::getVideoPlaybackQuality): Return a new VideoPlaybackQuality object.
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::incrementDroppedFrameCount): Simple incrementer.
+        * platform/MediaSample.h:
+        (WebCore::MediaSample::isSync): Convenience function.
+        (WebCore::MediaSample::isNonDisplaying): Ditto.
+
+        Add support in the AVFoundation MediaSource Engine:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::totalVideoFrames):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::droppedVideoFrames):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::corruptedVideoFrames):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::totalFrameDelay):
+
+        Add support in the Mock MediaSource Engine:
+        * platform/mock/mediasource/MockBox.h:
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
+        (WebCore::MockMediaPlayerMediaSource::totalVideoFrames): Simple accessor.
+        (WebCore::MockMediaPlayerMediaSource::droppedVideoFrames): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::corruptedVideoFrames): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::totalFrameDelay): Ditto.
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.h:
+        * platform/mock/mediasource/MockMediaSourcePrivate.cpp:
+        (WebCore::MockMediaSourcePrivate::MockMediaSourcePrivate):
+        * platform/mock/mediasource/MockMediaSourcePrivate.h:
+        * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+        (WebCore::MockSourceBufferPrivate::enqueueSample): Increment the frame counts based on
+            the incoming sample.
+        * platform/mock/mediasource/MockSourceBufferPrivate.h:
+
+        Add the new files to the project:
+        * bindings/gobject/GNUmakefile.am:
+        * DerivedSources.make:
+        * WebCore.xcodeproj/project.pbxproj:
+        * GNUMakefile.list.am:
+        * CMakeLists.txt:
+
</ins><span class="cx"> 2013-12-09  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Avoid divide by zero in scrollbar code, and protect against Obj-C exceptions
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/DerivedSources.make        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx">     $(WebCore)/Modules/mediasource/SourceBufferList.idl \
</span><span class="cx">         $(WebCore)/Modules/mediasource/TextTrackMediaSource.idl \
</span><span class="cx">         $(WebCore)/Modules/mediasource/VideoTrackMediaSource.idl \
</span><ins>+        $(WebCore)/Modules/mediasource/VideoPlaybackQuality.idl \
</ins><span class="cx">         $(WebCore)/Modules/mediastream/AllVideoCapabilities.idl \
</span><span class="cx">         $(WebCore)/Modules/mediastream/AllAudioCapabilities.idl \
</span><span class="cx">         $(WebCore)/Modules/mediastream/AudioStreamTrack.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreGNUmakefilelistam"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/GNUmakefile.list.am (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/GNUmakefile.list.am        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/GNUmakefile.list.am        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -735,6 +735,8 @@
</span><span class="cx">         DerivedSources/WebCore/JSValidityState.h \
</span><span class="cx">         DerivedSources/WebCore/JSVoidCallback.cpp \
</span><span class="cx">         DerivedSources/WebCore/JSVoidCallback.h \
</span><ins>+        DerivedSources/WebCore/JSVideoPlaybackQuality.h \
+        DerivedSources/WebCore/JSVideoPlaybackQuality.cpp \
</ins><span class="cx">         DerivedSources/WebCore/JSVideoStreamTrack.h \
</span><span class="cx">         DerivedSources/WebCore/JSVideoStreamTrack.cpp \
</span><span class="cx">         DerivedSources/WebCore/JSVideoTrack.cpp \
</span><span class="lines">@@ -1202,6 +1204,7 @@
</span><span class="cx">         $(WebCore)/Modules/mediasource/MediaSource.idl \
</span><span class="cx">         $(WebCore)/Modules/mediasource/SourceBuffer.idl \
</span><span class="cx">         $(WebCore)/Modules/mediasource/SourceBufferList.idl \
</span><ins>+        $(WebCore)/Modules/mediasource/VideoPlaybackQuality.idl \
</ins><span class="cx">         $(WebCore)/Modules/mediastream/AllVideoCapabilities.idl \
</span><span class="cx">         $(WebCore)/Modules/mediastream/AllAudioCapabilities.idl \
</span><span class="cx">         $(WebCore)/Modules/mediastream/AudioStreamTrack.idl \
</span><span class="lines">@@ -1884,6 +1887,8 @@
</span><span class="cx">         Source/WebCore/Modules/mediasource/DOMURLMediaSource.h \
</span><span class="cx">         Source/WebCore/Modules/mediasource/SampleMap.cpp \
</span><span class="cx">         Source/WebCore/Modules/mediasource/SampleMap.h \
</span><ins>+        Source/WebCore/Modules/mediasource/VideoPlaybackQuality.cpp \
+        Source/WebCore/Modules/mediasource/VideoPlaybackQuality.h \
</ins><span class="cx">         Source/WebCore/Modules/mediastream/AllAudioCapabilities.h \
</span><span class="cx">         Source/WebCore/Modules/mediastream/AllVideoCapabilities.h \
</span><span class="cx">         Source/WebCore/Modules/mediastream/AudioStreamTrack.cpp \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">         , lastFrameDuration(MediaTime::invalidTime())
</span><span class="cx">         , highestPresentationTimestamp(MediaTime::invalidTime())
</span><span class="cx">         , lastEnqueuedPresentationTime(MediaTime::invalidTime())
</span><del>-        , needRandomAccessFlag(false)
</del><ins>+        , needRandomAccessFlag(true)
</ins><span class="cx">         , enabled(false)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="lines">@@ -860,11 +860,18 @@
</span><span class="cx">         // FIXME: implement append windows
</span><span class="cx"> 
</span><span class="cx">         // 1.11 If the need random access point flag on track buffer equals true, then run the following steps:
</span><del>-        // 1.11.1 If the coded frame is not a random access point, then drop the coded frame and jump
-        // to the top of the loop to start processing the next coded frame.
-        // 1.11.2 Set the need random access point flag on track buffer to false.
-        // NOTE: MockSampleBoxes are not decodable.
</del><ins>+        if (trackBuffer.needRandomAccessFlag) {
+            // 1.11.1 If the coded frame is not a random access point, then drop the coded frame and jump
+            // to the top of the loop to start processing the next coded frame.
+            if (!sample-&gt;isSync()) {
+                didDropSample();
+                return;
+            }
</ins><span class="cx"> 
</span><ins>+            // 1.11.2 Set the need random access point flag on track buffer to false.
+            trackBuffer.needRandomAccessFlag = false;
+        }
+
</ins><span class="cx">         // 1.12 Let spliced audio frame be an unset variable for holding audio splice information
</span><span class="cx">         // 1.13 Let spliced timed text frame be an unset variable for holding timed text splice information
</span><span class="cx">         // FIXME: Add support for sample splicing.
</span><span class="lines">@@ -1146,6 +1153,12 @@
</span><span class="cx">     LOG(Media, &quot;SourceBuffer::provideMediaData(%p) - Enqueued %u samples&quot;, this, enqueuedSamples);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBuffer::didDropSample()
+{
+    if (!isRemoved())
+        m_source-&gt;mediaElement()-&gt;incrementDroppedFrameCount();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceSourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -141,6 +141,7 @@
</span><span class="cx">     bool validateInitializationSegment(const InitializationSegment&amp;);
</span><span class="cx"> 
</span><span class="cx">     void provideMediaData();
</span><ins>+    void didDropSample();
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;SourceBufferPrivate&gt; m_private;
</span><span class="cx">     MediaSource* m_source;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceVideoPlaybackQualitycpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.cpp (0 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;VideoPlaybackQuality.h&quot;
+
+namespace WebCore {
+
+RefPtr&lt;VideoPlaybackQuality&gt; VideoPlaybackQuality::create(double creationTime, unsigned long totalVideoFrames, unsigned long droppedVideoFrames, unsigned long corruptedVideoFrames, double totalFrameDelay)
+{
+    return adoptRef(new VideoPlaybackQuality(creationTime, totalVideoFrames, droppedVideoFrames, corruptedVideoFrames, totalFrameDelay));
+}
+
+VideoPlaybackQuality::VideoPlaybackQuality(double creationTime, unsigned long totalVideoFrames, unsigned long droppedVideoFrames, unsigned long corruptedVideoFrames, double totalFrameDelay)
+    : m_creationTime(creationTime)
+    , m_totalVideoFrames(totalVideoFrames)
+    , m_droppedVideoFrames(droppedVideoFrames)
+    , m_corruptedVideoFrames(corruptedVideoFrames)
+    , m_totalFrameDelay(totalFrameDelay)
+{
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceVideoPlaybackQualityh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.h (0 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VideoPlaybackQuality_h
+#define VideoPlaybackQuality_h
+
+#include &lt;wtf/RefCounted.h&gt;
+#include &lt;wtf/RefPtr.h&gt;
+
+namespace WebCore {
+
+class VideoPlaybackQuality : public RefCounted&lt;VideoPlaybackQuality&gt; {
+    WTF_MAKE_NONCOPYABLE(VideoPlaybackQuality)
+public:
+    static RefPtr&lt;VideoPlaybackQuality&gt; create(double creationTime, unsigned long totalVideoFrames, unsigned long droppedVideoFrames, unsigned long corruptedVideoFrames, double totalFrameDelay);
+
+    double creationTime() const { return m_creationTime; }
+    unsigned long totalVideoFrames() const { return m_totalVideoFrames; }
+    unsigned long droppedVideoFrames() const { return m_droppedVideoFrames; }
+    unsigned long corruptedVideoFrames() const { return m_corruptedVideoFrames; }
+    double totalFrameDelay() const { return m_totalFrameDelay; }
+
+protected:
+    VideoPlaybackQuality(double creationTime, unsigned long totalVideoFrames, unsigned long droppedVideoFrames, unsigned long corruptedVideoFrames, double totalFrameDelay);
+
+    double m_creationTime;
+    unsigned long m_totalVideoFrames;
+    unsigned long m_droppedVideoFrames;
+    unsigned long m_corruptedVideoFrames;
+    double m_totalFrameDelay;
+};
+
+}
+
+#endif // VideoPlaybackQuality_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceVideoPlaybackQualityidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.idl (0 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediasource/VideoPlaybackQuality.idl        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=MEDIA_SOURCE,
+    NoInterfaceObject,
+    ImplementationLacksVTable,
+] interface VideoPlaybackQuality {
+    readonly attribute double creationTime;
+    readonly attribute unsigned long totalVideoFrames;
+    readonly attribute unsigned long droppedVideoFrames;
+    readonly attribute unsigned long corruptedVideoFrames;
+    readonly attribute double totalFrameDelay;
+};
+
+
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -5418,6 +5418,9 @@
</span><span class="cx">                 CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */; };
</span><span class="cx">                 CDE7FC44181904B1002BBB77 /* OrderIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */; };
</span><span class="cx">                 CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE7FC43181904B1002BBB77 /* OrderIterator.h */; };
</span><ins>+                CDE83DB1183C44060031EAA3 /* VideoPlaybackQuality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE83DAF183C44060031EAA3 /* VideoPlaybackQuality.cpp */; };
+                CDE83DB2183C44060031EAA3 /* VideoPlaybackQuality.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE83DB0183C44060031EAA3 /* VideoPlaybackQuality.h */; };
+                CDE83DB6183D352A0031EAA3 /* JSVideoPlaybackQuality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE83DB4183D352A0031EAA3 /* JSVideoPlaybackQuality.cpp */; };
</ins><span class="cx">                 CDEA763014608A53008B31F1 /* PlatformClockCA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA762E146084DE008B31F1 /* PlatformClockCA.cpp */; };
</span><span class="cx">                 CDEA76341460B56F008B31F1 /* ClockGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA76321460AE29008B31F1 /* ClockGeneric.cpp */; };
</span><span class="cx">                 CDEA76351460B71A008B31F1 /* Clock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDEA76331460B462008B31F1 /* Clock.cpp */; };
</span><span class="lines">@@ -12543,6 +12546,11 @@
</span><span class="cx">                 CDE6560E17CA6E7600526BA7 /* mediaControlsApple.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = mediaControlsApple.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OrderIterator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE7FC43181904B1002BBB77 /* OrderIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                CDE83DAF183C44060031EAA3 /* VideoPlaybackQuality.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoPlaybackQuality.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE83DB0183C44060031EAA3 /* VideoPlaybackQuality.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoPlaybackQuality.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE83DB3183C441E0031EAA3 /* VideoPlaybackQuality.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = VideoPlaybackQuality.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE83DB4183D352A0031EAA3 /* JSVideoPlaybackQuality.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSVideoPlaybackQuality.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE83DB5183D352A0031EAA3 /* JSVideoPlaybackQuality.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVideoPlaybackQuality.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CDEA762C14608224008B31F1 /* Clock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDEA762E146084DE008B31F1 /* PlatformClockCA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformClockCA.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDEA762F146084EE008B31F1 /* PlatformClockCA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformClockCA.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -17769,6 +17777,8 @@
</span><span class="cx">                                 BE8EF048171C9014009B48C3 /* JSVideoTrackList.cpp */,
</span><span class="cx">                                 BE8EF049171C9014009B48C3 /* JSVideoTrackList.h */,
</span><span class="cx">                                 97E9EC8B15DC492F004F2E71 /* JSVoidCallback.cpp */,
</span><ins>+                                CDE83DB4183D352A0031EAA3 /* JSVideoPlaybackQuality.cpp */,
+                                CDE83DB5183D352A0031EAA3 /* JSVideoPlaybackQuality.h */,
</ins><span class="cx">                                 97E9EC8C15DC492F004F2E71 /* JSVoidCallback.h */,
</span><span class="cx">                                 A7D20F60107F406900A80392 /* JSWebGLActiveInfo.cpp */,
</span><span class="cx">                                 A7D20F61107F406900A80392 /* JSWebGLActiveInfo.h */,
</span><span class="lines">@@ -18574,6 +18584,9 @@
</span><span class="cx">                                 CD3A495D17A9D01B00274E42 /* SourceBufferList.idl */,
</span><span class="cx">                                 CD8B5A48180E138B008B8E65 /* TextTrackMediaSource.h */,
</span><span class="cx">                                 CD8B5A47180E1361008B8E65 /* TextTrackMediaSource.idl */,
</span><ins>+                                CDE83DAF183C44060031EAA3 /* VideoPlaybackQuality.cpp */,
+                                CDE83DB0183C44060031EAA3 /* VideoPlaybackQuality.h */,
+                                CDE83DB3183C441E0031EAA3 /* VideoPlaybackQuality.idl */,
</ins><span class="cx">                                 CD8B5A45180DFF4E008B8E65 /* VideoTrackMediaSource.h */,
</span><span class="cx">                                 CD8B5A44180DD8D6008B8E65 /* VideoTrackMediaSource.idl */,
</span><span class="cx">                                 CDD7089418359F6E002B3DC6 /* SampleMap.cpp */,
</span><span class="lines">@@ -23907,6 +23920,7 @@
</span><span class="cx">                                 B2FA3DFD0AB75A6F000E5AC4 /* JSSVGSVGElement.h in Headers */,
</span><span class="cx">                                 B2FA3DFF0AB75A6F000E5AC4 /* JSSVGSwitchElement.h in Headers */,
</span><span class="cx">                                 B2FA3E010AB75A6F000E5AC4 /* JSSVGSymbolElement.h in Headers */,
</span><ins>+                                CDE83DB2183C44060031EAA3 /* VideoPlaybackQuality.h in Headers */,
</ins><span class="cx">                                 B2FA3E030AB75A6F000E5AC4 /* JSSVGTextContentElement.h in Headers */,
</span><span class="cx">                                 B2FA3E050AB75A6F000E5AC4 /* JSSVGTextElement.h in Headers */,
</span><span class="cx">                                 B22362290C3AF04A0008CA9B /* JSSVGTextPathElement.h in Headers */,
</span><span class="lines">@@ -26432,6 +26446,7 @@
</span><span class="cx">                                 4FB390AD15EF61F3007AD51F /* GeneratedImage.cpp in Sources */,
</span><span class="cx">                                 2D481F03146B5C6500AA7834 /* GradientImage.cpp in Sources */,
</span><span class="cx">                                 0720B0A014D3323500642955 /* GenericEventQueue.cpp in Sources */,
</span><ins>+                                CDE83DB1183C44060031EAA3 /* VideoPlaybackQuality.cpp in Sources */,
</ins><span class="cx">                                 9746AF2314F4DDE6003E7A70 /* Geolocation.cpp in Sources */,
</span><span class="cx">                                 9746AF2614F4DDE6003E7A70 /* GeolocationController.cpp in Sources */,
</span><span class="cx">                                 B2C3DA6D0D006CD600EF6F26 /* GlyphPageTreeNode.cpp in Sources */,
</span><span class="lines">@@ -28025,6 +28040,7 @@
</span><span class="cx">                                 B22279A40D00BF220071B782 /* SVGComponentTransferFunctionElement.cpp in Sources */,
</span><span class="cx">                                 B2227B050D00BFF10071B782 /* SVGCSSComputedStyleDeclaration.cpp in Sources */,
</span><span class="cx">                                 078E090C17D14CEE00420AA1 /* RTCSessionDescription.cpp in Sources */,
</span><ins>+                                CDE83DB6183D352A0031EAA3 /* JSVideoPlaybackQuality.cpp in Sources */,
</ins><span class="cx">                                 B2227B060D00BFF10071B782 /* SVGCSSParser.cpp in Sources */,
</span><span class="cx">                                 B2227B080D00BFF10071B782 /* SVGCSSStyleSelector.cpp in Sources */,
</span><span class="cx">                                 B22279A70D00BF220071B782 /* SVGCursorElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsgobjectGNUmakefileam"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/gobject/GNUmakefile.am (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/gobject/GNUmakefile.am        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/bindings/gobject/GNUmakefile.am        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -443,6 +443,7 @@
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTextTrackCue.h \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTextTrackCueList.h \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTrackEvent.h \
</span><ins>+        DerivedSources/webkitdom/WebKitDOMVideoPlaybackQuality.h \
</ins><span class="cx">         DerivedSources/webkitdom/WebKitDOMVideoTrack.h \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMVideoTrackList.h
</span><span class="cx"> webkitgtk_gdom_built_sources += \
</span><span class="lines">@@ -460,6 +461,7 @@
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTextTrackCuePrivate.h \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTextTrackCueList.cpp \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTextTrackCueListPrivate.h \
</span><ins>+        DerivedSources/webkitdom/WebKitDOMVideoPlaybackQuality.cpp \
</ins><span class="cx">         DerivedSources/webkitdom/WebKitDOMVideoTrack.cpp \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMVideoTrackList.cpp \
</span><span class="cx">         DerivedSources/webkitdom/WebKitDOMTrackEvent.cpp \
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -108,7 +108,10 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><ins>+#include &quot;DOMWindow.h&quot;
</ins><span class="cx"> #include &quot;HTMLMediaSource.h&quot;
</span><ins>+#include &quot;Performance.h&quot;
+#include &quot;VideoPlaybackQuality.h&quot;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="lines">@@ -271,6 +274,9 @@
</span><span class="cx">     , m_preload(MediaPlayer::Auto)
</span><span class="cx">     , m_displayMode(Unknown)
</span><span class="cx">     , m_processingMediaPlayerCallback(0)
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+    , m_droppedVideoFrames(0)
+#endif
</ins><span class="cx">     , m_cachedTime(MediaPlayer::invalidTime())
</span><span class="cx">     , m_clockTimeAtLastCachedTimeUpdate(0)
</span><span class="cx">     , m_minimumClockTimeToUpdateCachedTime(0)
</span><span class="lines">@@ -3908,6 +3914,10 @@
</span><span class="cx">     if (renderer())
</span><span class="cx">         renderer()-&gt;updateFromElement();
</span><span class="cx">     endProcessingMediaPlayerCallback();
</span><ins>+
+#if ENABLE(MEDIA_SOURCE)
+    m_droppedVideoFrames = 0;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable(MediaPlayer*)
</span><span class="lines">@@ -5230,6 +5240,29 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+RefPtr&lt;VideoPlaybackQuality&gt; HTMLMediaElement::getVideoPlaybackQuality()
+{
+#if ENABLE(WEB_TIMING)
+    DOMWindow* domWindow = document().domWindow();
+    Performance* performance = domWindow ? domWindow-&gt;performance() : nullptr;
+    double now = performance ? performance-&gt;now() : 0;
+#else
+    DocumentLoader* loader = document().loader();
+    double now = loader ? 1000.0 * loader-&gt;timing()-&gt;monotonicTimeToZeroBasedDocumentTime(monotonicallyIncreasingTime()) : 0;
+#endif
+
+    if (!m_player)
+        return VideoPlaybackQuality::create(now, 0, 0, 0, 0);
+
+    return VideoPlaybackQuality::create(now,
+        m_droppedVideoFrames + m_player-&gt;totalVideoFrames(),
+        m_droppedVideoFrames + m_player-&gt;droppedVideoFrames(),
+        m_player-&gt;corruptedVideoFrames(),
+        m_player-&gt;totalFrameDelay());
+}
+#endif
+
</ins><span class="cx"> #if ENABLE(MEDIA_CONTROLS_SCRIPT)
</span><span class="cx"> DOMWrapperWorld&amp; HTMLMediaElement::ensureIsolatedWorld()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -80,6 +80,9 @@
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><span class="cx"> class MediaKeys;
</span><span class="cx"> #endif
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+class VideoPlaybackQuality;
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx"> class AudioTrackList;
</span><span class="lines">@@ -201,7 +204,8 @@
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><span class="cx"> //  Media Source.
</span><span class="cx">     void closeMediaSource();
</span><del>-#endif 
</del><ins>+    void incrementDroppedFrameCount() { ++m_droppedVideoFrames; }
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx">     void webkitGenerateKeyRequest(const String&amp; keySystem, PassRefPtr&lt;Uint8Array&gt; initData, ExceptionCode&amp;);
</span><span class="lines">@@ -398,6 +402,10 @@
</span><span class="cx">     void mediaLoadingFailed(MediaPlayer::NetworkState);
</span><span class="cx">     void mediaLoadingFailedFatally(MediaPlayer::NetworkState);
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+    RefPtr&lt;VideoPlaybackQuality&gt; getVideoPlaybackQuality();
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     HTMLMediaElement(const QualifiedName&amp;, Document&amp;, bool);
</span><span class="cx">     virtual ~HTMLMediaElement();
</span><span class="lines">@@ -699,6 +707,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><span class="cx">     RefPtr&lt;HTMLMediaSource&gt; m_mediaSource;
</span><ins>+    unsigned long m_droppedVideoFrames;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     mutable double m_cachedTime;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.idl (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.idl        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/html/HTMLMediaElement.idl        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -117,4 +117,6 @@
</span><span class="cx"> 
</span><span class="cx">     [Reflect, TreatNullAs=NullString] attribute DOMString mediaGroup;
</span><span class="cx">     [CustomSetter] attribute MediaController controller;
</span><ins>+    
+    [Conditional=MEDIA_SOURCE] VideoPlaybackQuality getVideoPlaybackQuality();
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMediaSampleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MediaSample.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MediaSample.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/MediaSample.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -63,6 +63,9 @@
</span><span class="cx">     };
</span><span class="cx">     virtual SampleFlags flags() const = 0;
</span><span class="cx">     virtual PlatformSample platformSample() = 0;
</span><ins>+
+    bool isSync() const { return flags() &amp; IsSync; }
+    bool isNonDisplaying() const { return flags() &amp; NonDisplaying; }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -1239,6 +1239,40 @@
</span><span class="cx">     return m_private-&gt;fileSize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+unsigned long MediaPlayer::totalVideoFrames()
+{
+    if (!m_private)
+        return 0;
+
+    return m_private-&gt;totalVideoFrames();
+}
+
+unsigned long MediaPlayer::droppedVideoFrames()
+{
+    if (!m_private)
+        return 0;
+
+    return m_private-&gt;droppedVideoFrames();
+}
+
+unsigned long MediaPlayer::corruptedVideoFrames()
+{
+    if (!m_private)
+        return 0;
+
+    return m_private-&gt;corruptedVideoFrames();
+}
+
+double MediaPlayer::totalFrameDelay()
+{
+    if (!m_private)
+        return 0;
+
+    return m_private-&gt;totalFrameDelay();
+}
+#endif
+
</ins><span class="cx"> void MediaPlayerFactorySupport::callRegisterMediaEngine(MediaEngineRegister registerMediaEngine)
</span><span class="cx"> {
</span><span class="cx">     registerMediaEngine(addMediaEngine);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -514,6 +514,13 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned long long fileSize() const;
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SOURCE)
+    unsigned long totalVideoFrames();
+    unsigned long droppedVideoFrames();
+    unsigned long corruptedVideoFrames();
+    double totalFrameDelay();
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx">     MediaPlayer(MediaPlayerClient*);
</span><span class="cx">     MediaPlayerFactory* nextBestMediaEngine(MediaPlayerFactory*) const;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -215,6 +215,13 @@
</span><span class="cx">     virtual size_t extraMemoryCost() const { return 0; }
</span><span class="cx">     
</span><span class="cx">     virtual unsigned long long fileSize() const { return 0; }
</span><ins>+
+#if ENABLE(MEDIA_SOURCE)
+    virtual unsigned long totalVideoFrames() { return 0; }
+    virtual unsigned long droppedVideoFrames() { return 0; }
+    virtual unsigned long corruptedVideoFrames() { return 0; }
+    virtual double totalFrameDelay() { return 0; }
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -129,6 +129,11 @@
</span><span class="cx"> 
</span><span class="cx">     virtual size_t extraMemoryCost() const OVERRIDE;
</span><span class="cx"> 
</span><ins>+    virtual unsigned long totalVideoFrames() OVERRIDE;
+    virtual unsigned long droppedVideoFrames() OVERRIDE;
+    virtual unsigned long corruptedVideoFrames() OVERRIDE;
+    virtual double totalFrameDelay() OVERRIDE;
+
</ins><span class="cx">     void ensureLayer();
</span><span class="cx">     void destroyLayer();
</span><span class="cx">     void durationChanged();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -50,7 +50,22 @@
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVURLAsset)
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVSampleBufferDisplayLayer)
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamDataParser)
</span><ins>+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVVideoPerformanceMetrics)
</ins><span class="cx"> 
</span><ins>+#pragma mark -
+#pragma mark AVVideoPerformanceMetrics
+
+@interface AVVideoPerformanceMetrics : NSObject
+- (unsigned long)totalNumberOfVideoFrames;
+- (unsigned long)numberOfDroppedVideoFrames;
+- (unsigned long)numberOfCorruptedVideoFrames;
+- (double)totalFrameDelay;
+@end
+
+@interface AVSampleBufferDisplayLayer (WebCoreAVSampleBufferDisplayLayerPrivate)
+- (AVVideoPerformanceMetrics *)videoPerformanceMetrics;
+@end
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> #pragma mark -
</span><span class="lines">@@ -366,6 +381,26 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned long MediaPlayerPrivateMediaSourceAVFObjC::totalVideoFrames()
+{
+    return [[m_sampleBufferDisplayLayer videoPerformanceMetrics] totalNumberOfVideoFrames];
+}
+
+unsigned long MediaPlayerPrivateMediaSourceAVFObjC::droppedVideoFrames()
+{
+    return [[m_sampleBufferDisplayLayer videoPerformanceMetrics] numberOfDroppedVideoFrames];
+}
+
+unsigned long MediaPlayerPrivateMediaSourceAVFObjC::corruptedVideoFrames()
+{
+    return [[m_sampleBufferDisplayLayer videoPerformanceMetrics] numberOfCorruptedVideoFrames];
+}
+
+double MediaPlayerPrivateMediaSourceAVFObjC::totalFrameDelay()
+{
+    return [[m_sampleBufferDisplayLayer videoPerformanceMetrics] totalFrameDelay];
+}
+
</ins><span class="cx"> #pragma mark -
</span><span class="cx"> #pragma mark Utility Methods
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockBoxh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockBox.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockBox.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockBox.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -129,8 +129,16 @@
</span><span class="cx">     int32_t trackID() const { return m_trackID; }
</span><span class="cx">     uint8_t flags() const { return m_flags; }
</span><span class="cx"> 
</span><del>-    enum { IsSync = 1 &lt;&lt; 0 };
</del><ins>+    enum {
+        IsSync = 1 &lt;&lt; 0,
+        IsCorrupted = 1 &lt;&lt; 1,
+        IsDropped = 1 &lt;&lt; 2,
+        IsDelayed = 1 &lt;&lt; 3,
+    };
</ins><span class="cx">     bool isSync() const { return m_flags &amp; IsSync; }
</span><ins>+    bool isCorrupted() const { return m_flags &amp; IsCorrupted; }
+    bool isDropped() const { return m_flags &amp; IsDropped; }
+    bool isDelayed() const { return m_flags &amp; IsDelayed; }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     MediaTime m_presentationTimestamp;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -245,6 +245,26 @@
</span><span class="cx">     m_player-&gt;networkStateChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned long MockMediaPlayerMediaSource::totalVideoFrames()
+{
+    return m_mediaSourcePrivate ? m_mediaSourcePrivate-&gt;totalVideoFrames() : 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned long MockMediaPlayerMediaSource::droppedVideoFrames()
+{
+    return m_mediaSourcePrivate ? m_mediaSourcePrivate-&gt;droppedVideoFrames() : 0;
+}
+
+unsigned long MockMediaPlayerMediaSource::corruptedVideoFrames()
+{
+    return m_mediaSourcePrivate ? m_mediaSourcePrivate-&gt;corruptedVideoFrames() : 0;
+}
+
+double MockMediaPlayerMediaSource::totalFrameDelay()
+{
+    return m_mediaSourcePrivate ? m_mediaSourcePrivate-&gt;totalFrameDelay() : 0;
+}
+
+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -77,6 +77,10 @@
</span><span class="cx">     virtual double currentTimeDouble() const OVERRIDE;
</span><span class="cx">     virtual double durationDouble() const OVERRIDE;
</span><span class="cx">     virtual void seekWithTolerance(double time, double, double) OVERRIDE;
</span><ins>+    virtual unsigned long totalVideoFrames() OVERRIDE;
+    virtual unsigned long droppedVideoFrames() OVERRIDE;
+    virtual unsigned long corruptedVideoFrames() OVERRIDE;
+    virtual double totalFrameDelay() OVERRIDE;
</ins><span class="cx"> 
</span><span class="cx">     MediaPlayer* m_player;
</span><span class="cx">     RefPtr&lt;HTMLMediaSource&gt; m_mediaSource;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -44,6 +44,10 @@
</span><span class="cx">     : m_player(parent)
</span><span class="cx">     , m_duration(std::numeric_limits&lt;float&gt;::quiet_NaN())
</span><span class="cx">     , m_isEnded(false)
</span><ins>+    , m_totalVideoFrames(0)
+    , m_droppedVideoFrames(0)
+    , m_corruptedVideoFrames(0)
+    , m_totalFrameDelay(0)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -52,6 +52,16 @@
</span><span class="cx">     void seekToTime(const MediaTime&amp;);
</span><span class="cx">     MediaTime seekToTime(const MediaTime&amp;, const MediaTime&amp; negativeThreshold, const MediaTime&amp; positiveThreshold);
</span><span class="cx"> 
</span><ins>+    unsigned long totalVideoFrames() const { return m_totalVideoFrames; }
+    unsigned long droppedVideoFrames() const  { return m_droppedVideoFrames; }
+    unsigned long corruptedVideoFrames() const { return m_corruptedVideoFrames; }
+    double totalFrameDelay() const { return m_totalFrameDelay; }
+
+    void incrementTotalVideoFrames() { ++m_totalVideoFrames; }
+    void incrementDroppedFrames() { ++m_droppedVideoFrames; }
+    void incrementCorruptedFrames() { ++m_corruptedVideoFrames; }
+    void incrementTotalFrameDelayBy(double delay) { m_totalFrameDelay += delay; }
+
</ins><span class="cx"> private:
</span><span class="cx">     MockMediaSourcePrivate(MockMediaPlayerMediaSource*);
</span><span class="cx"> 
</span><span class="lines">@@ -74,6 +84,11 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;MockSourceBufferPrivate&gt;&gt; m_sourceBuffers;
</span><span class="cx">     Vector&lt;MockSourceBufferPrivate*&gt; m_activeSourceBuffers;
</span><span class="cx">     bool m_isEnded;
</span><ins>+
+    unsigned long m_totalVideoFrames;
+    unsigned long m_droppedVideoFrames;
+    unsigned long m_corruptedVideoFrames;
+    double m_totalFrameDelay;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -218,6 +218,28 @@
</span><span class="cx">         m_mediaSource-&gt;sourceBufferPrivateDidChangeActiveState(this, isActive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockSourceBufferPrivate::enqueueSample(PassRefPtr&lt;MediaSample&gt; sample, AtomicString)
+{
+    if (!m_mediaSource || !sample)
+        return;
+
+    PlatformSample platformSample = sample-&gt;platformSample();
+    if (platformSample.type != PlatformSample::MockSampleBoxType)
+        return;
+
+    MockSampleBox* box = platformSample.sample.mockSampleBox;
+    if (!box)
+        return;
+
+    m_mediaSource-&gt;incrementTotalVideoFrames();
+    if (box-&gt;isCorrupted())
+        m_mediaSource-&gt;incrementCorruptedFrames();
+    if (box-&gt;isDropped())
+        m_mediaSource-&gt;incrementDroppedFrames();
+    if (box-&gt;isDelayed())
+        m_mediaSource-&gt;incrementTotalFrameDelayBy(1);
+}
+
</ins><span class="cx"> bool MockSourceBufferPrivate::hasVideo() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_client)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockSourceBufferPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h (160335 => 160336)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2013-12-09 23:27:42 UTC (rev 160335)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h        2013-12-09 23:36:56 UTC (rev 160336)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">     virtual bool isFull() OVERRIDE;
</span><span class="cx"> 
</span><span class="cx">     virtual void flushAndEnqueueNonDisplayingSamples(Vector&lt;RefPtr&lt;MediaSample&gt;&gt;, AtomicString) OVERRIDE { }
</span><del>-    virtual void enqueueSample(PassRefPtr&lt;MediaSample&gt;, AtomicString) OVERRIDE { }
</del><ins>+    virtual void enqueueSample(PassRefPtr&lt;MediaSample&gt;, AtomicString) OVERRIDE;
</ins><span class="cx">     virtual bool isReadyForMoreSamples() OVERRIDE { return true; }
</span><span class="cx">     virtual void setActive(bool) OVERRIDE;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>