<!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>[169536] 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/169536">169536</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2014-06-02 11:58:45 -0700 (Mon, 02 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MSE][Mac] Media does not generate 'ended' event when playing to duration.
https://bugs.webkit.org/show_bug.cgi?id=133452

Reviewed by Eric Carlson.

Add a boundaryTimeObserver to the AVSampleBufferRenderSynchronizer to detect when
playback crosses the duration boundary, and pause in that event. Also refuse to begin
playback if the currentTime is beyond the duration. Also, pause playback if duration
becomes less than currentTime.

* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playInternal):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::currentMediaTime):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::currentTimeDouble):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::durationChanged):

Update MediaSource::duration() and ::setDuration() to take and give MediaTimes rather than doubles:
* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::duration): double -&gt; MediaTime.
(WebCore::MediaSource::setDuration): Ditto.
(WebCore::MediaSource::streamEndedWithError): Ditto.
* platform/graphics/MediaSourcePrivate.h: Ditto.
* platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
(WebCore::MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC): Ditto.
(WebCore::MediaSourcePrivateAVFObjC::duration): Ditto.
(WebCore::MediaSourcePrivateAVFObjC::setDuration): Ditto.
* platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
(WebCore::MockMediaPlayerMediaSource::MockMediaPlayerMediaSource): Ditto.
(WebCore::MockMediaPlayerMediaSource::maxTimeSeekableDouble): Ditto.
(WebCore::MockMediaPlayerMediaSource::durationDouble): Ditto.
(WebCore::MockMediaPlayerMediaSource::advanceCurrentTime): Ditto.
(WebCore::MockMediaPlayerMediaSource::updateDuration): Ditto.
* platform/mock/mediasource/MockMediaPlayerMediaSource.h:
* platform/mock/mediasource/MockMediaSourcePrivate.cpp:
(WebCore::MockMediaSourcePrivate::MockMediaSourcePrivate): Ditto.
(WebCore::MockMediaSourcePrivate::duration): Ditto.
(WebCore::MockMediaSourcePrivate::setDuration): Ditto.
* platform/mock/mediasource/MockMediaSourcePrivate.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasourceMediaSourcecpp">trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaSourcePrivateh">trunk/Source/WebCore/platform/graphics/MediaSourcePrivate.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="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/ChangeLog        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2014-06-02  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [MSE][Mac] Media does not generate 'ended' event when playing to duration.
+        https://bugs.webkit.org/show_bug.cgi?id=133452
+
+        Reviewed by Eric Carlson.
+
+        Add a boundaryTimeObserver to the AVSampleBufferRenderSynchronizer to detect when
+        playback crosses the duration boundary, and pause in that event. Also refuse to begin
+        playback if the currentTime is beyond the duration. Also, pause playback if duration
+        becomes less than currentTime.
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playInternal):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::currentMediaTime):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::currentTimeDouble):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::durationChanged):
+
+        Update MediaSource::duration() and ::setDuration() to take and give MediaTimes rather than doubles:
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::duration): double -&gt; MediaTime.
+        (WebCore::MediaSource::setDuration): Ditto.
+        (WebCore::MediaSource::streamEndedWithError): Ditto.
+        * platform/graphics/MediaSourcePrivate.h: Ditto.
+        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
+        (WebCore::MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC): Ditto.
+        (WebCore::MediaSourcePrivateAVFObjC::duration): Ditto.
+        (WebCore::MediaSourcePrivateAVFObjC::setDuration): Ditto.
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.cpp:
+        (WebCore::MockMediaPlayerMediaSource::MockMediaPlayerMediaSource): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::maxTimeSeekableDouble): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::durationDouble): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::advanceCurrentTime): Ditto.
+        (WebCore::MockMediaPlayerMediaSource::updateDuration): Ditto.
+        * platform/mock/mediasource/MockMediaPlayerMediaSource.h:
+        * platform/mock/mediasource/MockMediaSourcePrivate.cpp:
+        (WebCore::MockMediaSourcePrivate::MockMediaSourcePrivate): Ditto.
+        (WebCore::MockMediaSourcePrivate::duration): Ditto.
+        (WebCore::MockMediaSourcePrivate::setDuration): Ditto.
+        * platform/mock/mediasource/MockMediaSourcePrivate.h:
+
</ins><span class="cx"> 2014-06-02  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rename ImagePaintingContext to ImagePaintingOptions.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasourceMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx"> 
</span><span class="cx"> double MediaSource::duration() const
</span><span class="cx"> {
</span><del>-    return isClosed() ? std::numeric_limits&lt;float&gt;::quiet_NaN() : m_private-&gt;duration();
</del><ins>+    return isClosed() ? std::numeric_limits&lt;float&gt;::quiet_NaN() : m_private-&gt;duration().toDouble();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double MediaSource::currentTime() const
</span><span class="lines">@@ -260,7 +260,7 @@
</span><span class="cx">         ec = INVALID_STATE_ERR;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    m_private-&gt;setDuration(duration);
</del><ins>+    m_private-&gt;setDuration(MediaTime::createWithDouble(duration));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -328,7 +328,7 @@
</span><span class="cx">         MediaTime maxEndTimestamp;
</span><span class="cx">         for (auto it = m_sourceBuffers-&gt;begin(), end = m_sourceBuffers-&gt;end(); it != end; ++it)
</span><span class="cx">             maxEndTimestamp = std::max((*it)-&gt;highestPresentationEndTimestamp(), maxEndTimestamp);
</span><del>-        m_private-&gt;setDuration(maxEndTimestamp.toDouble());
</del><ins>+        m_private-&gt;setDuration(maxEndTimestamp);
</ins><span class="cx"> 
</span><span class="cx">         // 2. Notify the media element that it now has all of the media data.
</span><span class="cx">         m_private-&gt;markEndOfStream(MediaSourcePrivate::EosNoError);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaSourcePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaSourcePrivate.h (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaSourcePrivate.h        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/graphics/MediaSourcePrivate.h        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -51,8 +51,8 @@
</span><span class="cx"> 
</span><span class="cx">     enum AddStatus { Ok, NotSupported, ReachedIdLimit };
</span><span class="cx">     virtual AddStatus addSourceBuffer(const ContentType&amp;, RefPtr&lt;SourceBufferPrivate&gt;&amp;) = 0;
</span><del>-    virtual double duration() = 0;
-    virtual void setDuration(double) = 0;
</del><ins>+    virtual MediaTime duration() = 0;
+    virtual void setDuration(const MediaTime&amp;) = 0;
</ins><span class="cx">     enum EndOfStreamStatus { EosNoError, EosNetworkError, EosDecodeError };
</span><span class="cx">     virtual void markEndOfStream(EndOfStreamStatus) = 0;
</span><span class="cx">     virtual void unmarkEndOfStream() = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -152,6 +152,8 @@
</span><span class="cx">     virtual unsigned long corruptedVideoFrames() override;
</span><span class="cx">     virtual double totalFrameDelay() override;
</span><span class="cx"> 
</span><ins>+    MediaTime currentMediaTime() const;
+
</ins><span class="cx">     void ensureLayer();
</span><span class="cx">     void destroyLayer();
</span><span class="cx"> 
</span><span class="lines">@@ -173,6 +175,7 @@
</span><span class="cx">     Vector&lt;RetainPtr&lt;AVSampleBufferAudioRenderer&gt;&gt; m_sampleBufferAudioRenderers;
</span><span class="cx">     RetainPtr&lt;AVSampleBufferRenderSynchronizer&gt; m_synchronizer;
</span><span class="cx">     RetainPtr&lt;id&gt; m_timeJumpedObserver;
</span><ins>+    RetainPtr&lt;id&gt; m_durationObserver;
</ins><span class="cx">     MediaPlayer::NetworkState m_networkState;
</span><span class="cx">     MediaPlayer::ReadyState m_readyState;
</span><span class="cx">     double m_rate;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #import &quot;SoftLinking.h&quot;
</span><span class="cx"> #import &quot;WebCoreSystemInterface.h&quot;
</span><span class="cx"> #import &lt;AVFoundation/AVAsset.h&gt;
</span><ins>+#import &lt;AVFoundation/AVTime.h&gt;
</ins><span class="cx"> #import &lt;CoreMedia/CMSync.h&gt;
</span><span class="cx"> #import &lt;QuartzCore/CALayer.h&gt;
</span><span class="cx"> #import &lt;objc_runtime.h&gt;
</span><span class="lines">@@ -109,6 +110,7 @@
</span><span class="cx"> - (void)addRenderer:(id)renderer;
</span><span class="cx"> - (void)removeRenderer:(id)renderer atTime:(CMTime)time withCompletionHandler:(void (^)(BOOL didRemoveRenderer))completionHandler;
</span><span class="cx"> - (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
</span><ins>+- (id)addBoundaryTimeObserverForTimes:(NSArray *)times queue:(dispatch_queue_t)queue usingBlock:(void (^)(void))block;
</ins><span class="cx"> - (void)removeTimeObserver:(id)observer;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="lines">@@ -164,6 +166,7 @@
</span><span class="cx">     CMNotificationCenterRemoveListener(nc, this, CMTimebaseEffectiveRateChangedCallback, kCMTimebaseNotification_EffectiveRateChanged, timebase);
</span><span class="cx"> 
</span><span class="cx">     [m_synchronizer removeTimeObserver:m_timeJumpedObserver.get()];
</span><ins>+    [m_synchronizer removeTimeObserver:m_durationObserver.get()];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #pragma mark -
</span><span class="lines">@@ -316,6 +319,9 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::playInternal()
</span><span class="cx"> {
</span><ins>+    if (currentMediaTime() &gt;= m_mediaSourcePrivate-&gt;duration())
+        return;
+
</ins><span class="cx">     m_playing = true;
</span><span class="cx">     [m_synchronizer setRate:m_rate];
</span><span class="cx"> }
</span><span class="lines">@@ -389,9 +395,14 @@
</span><span class="cx">     return m_mediaSource-&gt;duration();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MediaTime MediaPlayerPrivateMediaSourceAVFObjC::currentMediaTime() const
+{
+    return std::max(MediaTime::zeroTime(), toMediaTime(CMTimebaseGetTime([m_synchronizer timebase])));
+}
+
</ins><span class="cx"> double MediaPlayerPrivateMediaSourceAVFObjC::currentTimeDouble() const
</span><span class="cx"> {
</span><del>-    return std::max&lt;double&gt;(0, CMTimeGetSeconds(CMTimebaseGetTime([m_synchronizer timebase])));
</del><ins>+    return currentMediaTime().toDouble();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double MediaPlayerPrivateMediaSourceAVFObjC::startTimeDouble() const
</span><span class="lines">@@ -585,6 +596,23 @@
</span><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::durationChanged()
</span><span class="cx"> {
</span><span class="cx">     m_player-&gt;durationChanged();
</span><ins>+
+    if (m_durationObserver)
+        [m_synchronizer removeTimeObserver:m_durationObserver.get()];
+
+    if (!m_mediaSourcePrivate)
+        return;
+
+    MediaTime duration = m_mediaSourcePrivate-&gt;duration();
+    auto weakThis = createWeakPtr();
+    NSArray* times = @[[NSValue valueWithCMTime:toCMTime(duration)]];
+    m_durationObserver = [m_synchronizer addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:[weakThis] {
+        if (weakThis)
+            weakThis-&gt;pauseInternal();
+    }];
+
+    if (m_playing &amp;&amp; duration &lt;= currentMediaTime())
+        pauseInternal();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::effectiveRateChanged()
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -57,8 +57,8 @@
</span><span class="cx">     const Vector&lt;SourceBufferPrivateAVFObjC*&gt;&amp; activeSourceBuffers() const { return m_activeSourceBuffers; }
</span><span class="cx"> 
</span><span class="cx">     virtual AddStatus addSourceBuffer(const ContentType&amp;, RefPtr&lt;SourceBufferPrivate&gt;&amp;) override;
</span><del>-    virtual double duration() override;
-    virtual void setDuration(double) override;
</del><ins>+    virtual MediaTime duration() override;
+    virtual void setDuration(const MediaTime&amp;) override;
</ins><span class="cx">     virtual void markEndOfStream(EndOfStreamStatus) override;
</span><span class="cx">     virtual void unmarkEndOfStream() override;
</span><span class="cx">     virtual MediaPlayer::ReadyState readyState() const override;
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">     friend class SourceBufferPrivateAVFObjC;
</span><span class="cx"> 
</span><span class="cx">     MediaPlayerPrivateMediaSourceAVFObjC* m_player;
</span><del>-    double m_duration;
</del><ins>+    MediaTime m_duration;
</ins><span class="cx">     Vector&lt;RefPtr&lt;SourceBufferPrivateAVFObjC&gt;&gt; m_sourceBuffers;
</span><span class="cx">     Vector&lt;SourceBufferPrivateAVFObjC*&gt; m_activeSourceBuffers;
</span><span class="cx">     Deque&lt;SourceBufferPrivateAVFObjC*&gt; m_sourceBuffersNeedingSessions;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaSourcePrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> 
</span><span class="cx"> MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC* parent)
</span><span class="cx">     : m_player(parent)
</span><del>-    , m_duration(std::numeric_limits&lt;double&gt;::quiet_NaN())
</del><ins>+    , m_duration(MediaTime::invalidTime())
</ins><span class="cx">     , m_isEnded(false)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -89,12 +89,12 @@
</span><span class="cx">     m_sourceBuffers.remove(pos);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-double MediaSourcePrivateAVFObjC::duration()
</del><ins>+MediaTime MediaSourcePrivateAVFObjC::duration()
</ins><span class="cx"> {
</span><span class="cx">     return m_duration;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaSourcePrivateAVFObjC::setDuration(double duration)
</del><ins>+void MediaSourcePrivateAVFObjC::setDuration(const MediaTime&amp; duration)
</ins><span class="cx"> {
</span><span class="cx">     if (duration == m_duration)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx"> MockMediaPlayerMediaSource::MockMediaPlayerMediaSource(MediaPlayer* player)
</span><span class="cx">     : m_player(player)
</span><span class="cx">     , m_currentTime(MediaTime::zeroTime())
</span><del>-    , m_duration(0)
</del><ins>+    , m_duration(MediaTime::zeroTime())
</ins><span class="cx">     , m_readyState(MediaPlayer::HaveNothing)
</span><span class="cx">     , m_networkState(MediaPlayer::Empty)
</span><span class="cx">     , m_playing(false)
</span><span class="lines">@@ -163,7 +163,7 @@
</span><span class="cx"> 
</span><span class="cx"> double MockMediaPlayerMediaSource::maxTimeSeekableDouble() const
</span><span class="cx"> {
</span><del>-    return m_duration;
</del><ins>+    return m_duration.toDouble();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;PlatformTimeRanges&gt; MockMediaPlayerMediaSource::buffered() const
</span><span class="lines">@@ -194,7 +194,7 @@
</span><span class="cx"> 
</span><span class="cx"> double MockMediaPlayerMediaSource::durationDouble() const
</span><span class="cx"> {
</span><del>-    return m_duration;
</del><ins>+    return m_duration.toDouble();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockMediaPlayerMediaSource::seekWithTolerance(double time, double negativeTolerance, double positiveTolerance)
</span><span class="lines">@@ -221,11 +221,11 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     bool ignoreError;
</span><del>-    m_currentTime = MediaTime::createWithDouble(std::min(m_duration, buffered-&gt;end(pos, ignoreError)));
</del><ins>+    m_currentTime = std::min(m_duration, MediaTime::createWithDouble(buffered-&gt;end(pos, ignoreError)));
</ins><span class="cx">     m_player-&gt;timeChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockMediaPlayerMediaSource::updateDuration(double duration)
</del><ins>+void MockMediaPlayerMediaSource::updateDuration(const MediaTime&amp; duration)
</ins><span class="cx"> {
</span><span class="cx">     if (m_duration == duration)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaPlayerMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     virtual ~MockMediaPlayerMediaSource();
</span><span class="cx"> 
</span><span class="cx">     void advanceCurrentTime();
</span><del>-    void updateDuration(double);
</del><ins>+    void updateDuration(const MediaTime&amp;);
</ins><span class="cx"> 
</span><span class="cx">     virtual MediaPlayer::ReadyState readyState() const override;
</span><span class="cx">     void setReadyState(MediaPlayer::ReadyState);
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx">     RefPtr&lt;MockMediaSourcePrivate&gt; m_mediaSourcePrivate;
</span><span class="cx"> 
</span><span class="cx">     MediaTime m_currentTime;
</span><del>-    double m_duration;
</del><ins>+    MediaTime m_duration;
</ins><span class="cx">     MediaPlayer::ReadyState m_readyState;
</span><span class="cx">     MediaPlayer::NetworkState m_networkState;
</span><span class="cx">     bool m_playing;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> MockMediaSourcePrivate::MockMediaSourcePrivate(MockMediaPlayerMediaSource* parent)
</span><span class="cx">     : m_player(parent)
</span><del>-    , m_duration(std::numeric_limits&lt;float&gt;::quiet_NaN())
</del><ins>+    , m_duration(MediaTime::invalidTime())
</ins><span class="cx">     , m_isEnded(false)
</span><span class="cx">     , m_totalVideoFrames(0)
</span><span class="cx">     , m_droppedVideoFrames(0)
</span><span class="lines">@@ -84,12 +84,12 @@
</span><span class="cx">     m_sourceBuffers.remove(pos);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-double MockMediaSourcePrivate::duration()
</del><ins>+MediaTime MockMediaSourcePrivate::duration()
</ins><span class="cx"> {
</span><span class="cx">     return m_duration;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockMediaSourcePrivate::setDuration(double duration)
</del><ins>+void MockMediaSourcePrivate::setDuration(const MediaTime&amp; duration)
</ins><span class="cx"> {
</span><span class="cx">     if (duration == m_duration)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockmediasourceMockMediaSourcePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h (169535 => 169536)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2014-06-02 18:19:28 UTC (rev 169535)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h        2014-06-02 18:58:45 UTC (rev 169536)
</span><span class="lines">@@ -67,8 +67,8 @@
</span><span class="cx"> 
</span><span class="cx">     // MediaSourcePrivate Overrides
</span><span class="cx">     virtual AddStatus addSourceBuffer(const ContentType&amp;, RefPtr&lt;SourceBufferPrivate&gt;&amp;) override;
</span><del>-    virtual double duration() override;
-    virtual void setDuration(double) override;
</del><ins>+    virtual MediaTime duration() override;
+    virtual void setDuration(const MediaTime&amp;) override;
</ins><span class="cx">     virtual void markEndOfStream(EndOfStreamStatus) override;
</span><span class="cx">     virtual void unmarkEndOfStream() override;
</span><span class="cx">     virtual MediaPlayer::ReadyState readyState() const override;
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">     friend class MockSourceBufferPrivate;
</span><span class="cx"> 
</span><span class="cx">     MockMediaPlayerMediaSource* m_player;
</span><del>-    double m_duration;
</del><ins>+    MediaTime m_duration;
</ins><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></span></pre>
</div>
</div>

</body>
</html>