Title: [159208] trunk
Revision
159208
Author
[email protected]
Date
2013-11-13 10:30:03 -0800 (Wed, 13 Nov 2013)

Log Message

Add support for HTMLMediaElement.fastSeek()
https://bugs.webkit.org/show_bug.cgi?id=124262

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/video-fast-seek.html

Add the fastSeek() method to HTMLMediaElement, and use fastSeek() in
the _javascript_ media controls.

Add the new fastSeek() method:
* html/HTMLMediaElement.cpp:
(HTMLMediaElement::fastSeek): Call seekWithTolerance.
(HTMLMediaElement::seek): Call seekWithTolerance with 0 tolerance.
(HTMLMediaElement::seekWithTolerance): Renamed from seek().
* html/HTMLMediaElement.h:
* html/HTMLMediaElement.idl:

Add seekWithTolerance() to MediaPlayer:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::seekWithTolerance): Pass to MediaPlayerPrivate.
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::seekWithTolerance): Default implementation which
    calls seek().
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::seek): Call seekWithTolerance with 0 tolerance.
(WebCore::MediaPlayerPrivateAVFoundation::seekWithTolerance): Renamed from seek().
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::seekToTime): Take tolerance parameters.

Use the new fastSeek() method while actively scrubbing.
* Modules/mediacontrols/mediaControlsApple.js:
(Controller.prototype.createControls): Add mouse up and down handlers.
(Controller.prototype.handleTimeUpdate): Only update the timeline when not scrubbing.
(Controller.prototype.handleTimelineChange): Use fastSeek().
(Controller.prototype.handleTimelineMouseDown): Start scrubbing.
(Controller.prototype.handleTimelineMouseUp): Stop scrubbing.

LayoutTests:

* media/video-fast-seek-expected.txt: Added.
* media/video-fast-seek.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (159207 => 159208)


--- trunk/LayoutTests/ChangeLog	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/LayoutTests/ChangeLog	2013-11-13 18:30:03 UTC (rev 159208)
@@ -1,3 +1,13 @@
+2013-11-12  Jer Noble  <[email protected]>
+
+        Add support for HTMLMediaElement.fastSeek()
+        https://bugs.webkit.org/show_bug.cgi?id=124262
+
+        Reviewed by Eric Carlson.
+
+        * media/video-fast-seek-expected.txt: Added.
+        * media/video-fast-seek.html: Added.
+
 2013-11-13  Antti Koivisto  <[email protected]>
 
         * TestExpectations: Skip crypto/subtle/rsassa-pkcs1-v1_5-import-jwk.html

Added: trunk/LayoutTests/media/video-fast-seek-expected.txt (0 => 159208)


--- trunk/LayoutTests/media/video-fast-seek-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-fast-seek-expected.txt	2013-11-13 18:30:03 UTC (rev 159208)
@@ -0,0 +1,22 @@
+
+Test that fastSeek() commands work correctly.
+
+EVENT(canplaythrough)
+Seek past the 4th sync sample:
+RUN(video.currentTime = 2.5)
+EVENT(timeupdate)
+EXPECTED (video.currentTime == '2.5') OK
+Test that fastSeek() past the currentTime will not result in a seek before the currentTime:
+RUN(video.fastSeek(2.6))
+EVENT(timeupdate)
+EXPECTED (video.currentTime >= '2.6') OK
+Seek before the 4th sync sample:
+RUN(video.currentTime = 2.3)
+EVENT(timeupdate)
+EXPECTED (video.currentTime == '2.3') OK
+Test that fastSeek() before the currentTime will not result in a seek past the currentTime:
+RUN(video.fastSeek(2.2))
+EVENT(timeupdate)
+EXPECTED (video.currentTime <= '2.2') OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-fast-seek.html (0 => 159208)


--- trunk/LayoutTests/media/video-fast-seek.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-fast-seek.html	2013-11-13 18:30:03 UTC (rev 159208)
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script>
+
+        // The test.mp4 file has sync samples at the following presentation time stamps:
+        // 0.0000, 0.7968, 1.5936, 2.3904, 3.1872, 3.9840, 4.7808, 5.5776
+
+        function runTest()
+        {
+            findMediaElement();
+            waitForEvent('canplaythrough', canplaythrough);
+
+            // Other media files may have sync samples at completely different points, so
+            // explicitly use the .mp4 here.
+            video.src = ""
+        }
+
+        function canplaythrough()
+        {
+            waitForEventOnce('timeupdate', seek1);
+            consoleWrite('Seek past the 4th sync sample:');
+            run('video.currentTime = 2.5');
+        }
+
+        function seek1()
+        {
+            testExpected('video.currentTime', 2.5);
+            consoleWrite('Test that fastSeek() past the currentTime will not result in a seek before the currentTime:');
+            waitForEventOnce('timeupdate', seek2);
+            run('video.fastSeek(2.6)');
+        }
+
+        function seek2()
+        {
+            testExpected('video.currentTime', 2.6, '>=');
+            consoleWrite('Seek before the 4th sync sample:');
+            waitForEventOnce('timeupdate', seek3);
+            run('video.currentTime = 2.3');
+        }
+
+        function seek3()
+        {
+            testExpected('video.currentTime', 2.3);
+            consoleWrite('Test that fastSeek() before the currentTime will not result in a seek past the currentTime:');
+            waitForEventOnce('timeupdate', seek4);
+            run('video.fastSeek(2.2)');
+        }
+
+        function seek4()
+        {
+            testExpected('video.currentTime', 2.2, '<=');
+            endTest();
+        }
+
+    </script>
+</head>
+<body _onload_="runTest()">
+    <video controls></video>
+    <p>Test that fastSeek() commands work correctly.</p>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (159207 => 159208)


--- trunk/Source/WebCore/ChangeLog	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/ChangeLog	2013-11-13 18:30:03 UTC (rev 159208)
@@ -1,3 +1,46 @@
+2013-11-12  Jer Noble  <[email protected]>
+
+        Add support for HTMLMediaElement.fastSeek()
+        https://bugs.webkit.org/show_bug.cgi?id=124262
+
+        Reviewed by Eric Carlson.
+
+        Test: media/video-fast-seek.html
+
+        Add the fastSeek() method to HTMLMediaElement, and use fastSeek() in
+        the _javascript_ media controls.
+
+        Add the new fastSeek() method:
+        * html/HTMLMediaElement.cpp:
+        (HTMLMediaElement::fastSeek): Call seekWithTolerance.
+        (HTMLMediaElement::seek): Call seekWithTolerance with 0 tolerance.
+        (HTMLMediaElement::seekWithTolerance): Renamed from seek().
+        * html/HTMLMediaElement.h:
+        * html/HTMLMediaElement.idl:
+
+        Add seekWithTolerance() to MediaPlayer:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::seekWithTolerance): Pass to MediaPlayerPrivate.
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::seekWithTolerance): Default implementation which
+            calls seek().
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::seek): Call seekWithTolerance with 0 tolerance.
+        (WebCore::MediaPlayerPrivateAVFoundation::seekWithTolerance): Renamed from seek().
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::seekToTime): Take tolerance parameters.
+
+        Use the new fastSeek() method while actively scrubbing.
+        * Modules/mediacontrols/mediaControlsApple.js:
+        (Controller.prototype.createControls): Add mouse up and down handlers.
+        (Controller.prototype.handleTimeUpdate): Only update the timeline when not scrubbing.
+        (Controller.prototype.handleTimelineChange): Use fastSeek().
+        (Controller.prototype.handleTimelineMouseDown): Start scrubbing.
+        (Controller.prototype.handleTimelineMouseUp): Stop scrubbing.
+
 2013-11-13  Andreas Kling  <[email protected]>
 
         Generate casting helpers for scrolling tree classes.

Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js (159207 => 159208)


--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2013-11-13 18:30:03 UTC (rev 159208)
@@ -295,6 +295,8 @@
         this.listenFor(timeline, 'mouseover', this.handleTimelineMouseOver);
         this.listenFor(timeline, 'mouseout', this.handleTimelineMouseOut);
         this.listenFor(timeline, 'mousemove', this.handleTimelineMouseMove);
+        this.listenFor(timeline, 'mousedown', this.handleTimelineMouseDown);
+        this.listenFor(timeline, 'mouseup', this.handleTimelineMouseUp);
         timeline.step = .01;
 
         var thumbnailTrack = this.controls.thumbnailTrack = document.createElement('div');
@@ -463,7 +465,8 @@
 
     handleTimeUpdate: function(event)
     {
-        this.updateTime();
+        if (!this.scrubbing)
+            this.updateTime();
     },
 
     handleDurationChange: function(event)
@@ -622,7 +625,7 @@
 
     handleTimelineChange: function(event)
     {
-        this.video.currentTime = this.controls.timeline.value;
+        this.video.fastSeek(this.controls.timeline.value);
     },
 
     handleTimelineDown: function(event)
@@ -675,6 +678,19 @@
         }
     },
 
+    handleTimelineMouseDown: function(event)
+    {
+        this.scrubbing = true;
+    },
+
+    handleTimelineMouseUp: function(event)
+    {
+        this.scrubbing = false;
+
+        // Do a precise seek when we lift the mouse:
+        this.video.currentTime = this.controls.timeline.value;
+    },
+
     handleMuteButtonClicked: function(event)
     {
         this.video.muted = !this.video.muted;

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (159207 => 159208)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2013-11-13 18:30:03 UTC (rev 159208)
@@ -2146,10 +2146,31 @@
     m_player->prepareToPlay();
 }
 
+void HTMLMediaElement::fastSeek(double time, ExceptionCode& ec)
+{
+    LOG(Media, "HTMLMediaElement::fastSeek(%f)", time);
+    // 4.7.10.9 Seeking
+    // 9. If the approximate-for-speed flag is set, adjust the new playback position to a value that will
+    // allow for playback to resume promptly. If new playback position before this step is before current
+    // playback position, then the adjusted new playback position must also be before the current playback
+    // position. Similarly, if the new playback position before this step is after current playback position,
+    // then the adjusted new playback position must also be after the current playback position.
+    refreshCachedTime();
+    double delta = time - currentTime();
+    double negativeTolerance = delta >= 0 ? delta : std::numeric_limits<double>::infinity();
+    double positiveTolerance = delta < 0 ? -delta : std::numeric_limits<double>::infinity();
+
+    seekWithTolerance(time, negativeTolerance, positiveTolerance, ec);
+}
+
 void HTMLMediaElement::seek(double time, ExceptionCode& ec)
 {
     LOG(Media, "HTMLMediaElement::seek(%f)", time);
+    seekWithTolerance(time, 0, 0, ec);
+}
 
+void HTMLMediaElement::seekWithTolerance(double time, double negativeTolerance, double positiveTolerance, ExceptionCode& ec)
+{
     // 4.8.9.9 Seeking
 
     // 1 - If the media element's readyState is HAVE_NOTHING, then raise an INVALID_STATE_ERR exception.
@@ -2232,7 +2253,7 @@
     m_sentEndEvent = false;
 
     // 8 - Set the current playback position to the given new playback position
-    m_player->seek(time);
+    m_player->seekWithTolerance(time, negativeTolerance, positiveTolerance);
 
     // 9 - Queue a task to fire a simple event named seeking at the element.
     scheduleEvent(eventNames().seekingEvent);

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (159207 => 159208)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2013-11-13 18:30:03 UTC (rev 159208)
@@ -178,6 +178,7 @@
     void setLoop(bool b);
     virtual void play() OVERRIDE;
     virtual void pause() OVERRIDE;
+    void fastSeek(double, ExceptionCode&);
 
 // captions
     bool webkitHasClosedCaptions() const;
@@ -536,6 +537,7 @@
     void stopPeriodicTimers();
 
     void seek(double time, ExceptionCode&);
+    void seekWithTolerance(double time, double negativeTolerance, double positiveTolerance, ExceptionCode&);
     void finishSeek();
     void checkIfSeekNeeded();
     void addPlayedRange(double start, double end);

Modified: trunk/Source/WebCore/html/HTMLMediaElement.idl (159207 => 159208)


--- trunk/Source/WebCore/html/HTMLMediaElement.idl	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/html/HTMLMediaElement.idl	2013-11-13 18:30:03 UTC (rev 159208)
@@ -75,6 +75,7 @@
 [Reflect] attribute boolean loop;
 void play();
 void pause();
+[RaisesException] void fastSeek(double time);
 
 // controls
 attribute boolean controls;

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2013-11-13 18:30:03 UTC (rev 159208)
@@ -538,6 +538,11 @@
     return m_private->currentTimeDouble();
 }
 
+void MediaPlayer::seekWithTolerance(double time, double negativeTolerance, double positiveTolerance)
+{
+    m_private->seekWithTolerance(time, negativeTolerance, positiveTolerance);
+}
+
 void MediaPlayer::seek(double time)
 {
     m_private->seekDouble(time);

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2013-11-13 18:30:03 UTC (rev 159208)
@@ -326,6 +326,7 @@
     double duration() const;
     double currentTime() const;
     void seek(double time);
+    void seekWithTolerance(double time, double negativeTolerance, double positiveTolerance);
 
     double startTime() const;
 

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2013-11-13 18:30:03 UTC (rev 159208)
@@ -79,6 +79,7 @@
 
     virtual void seek(float) { }
     virtual void seekDouble(double time) { seek(time); }
+    virtual void seekWithTolerance(double time, double, double) { seek(time); }
 
     virtual bool seeking() const = 0;
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp	2013-11-13 18:30:03 UTC (rev 159208)
@@ -266,6 +266,11 @@
 
 void MediaPlayerPrivateAVFoundation::seek(float time)
 {
+    seekWithTolerance(time, 0, 0);
+}
+
+void MediaPlayerPrivateAVFoundation::seekWithTolerance(double time, double negativeTolerance, double positiveTolerance)
+{
     if (!metaDataAvailable())
         return;
 
@@ -282,7 +287,7 @@
     m_seekTo = time;
 
     ++m_seekCount;
-    seekToTime(time);
+    seekToTime(time, negativeTolerance, positiveTolerance);
 }
 
 void MediaPlayerPrivateAVFoundation::setRate(float rate)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h	2013-11-13 18:30:03 UTC (rev 159208)
@@ -159,6 +159,7 @@
     virtual float duration() const OVERRIDE;
     virtual float currentTime() const = 0;
     virtual void seek(float) OVERRIDE;
+    virtual void seekWithTolerance(double, double, double) OVERRIDE;
     virtual bool seeking() const OVERRIDE;
     virtual void setRate(float) OVERRIDE;
     virtual bool paused() const OVERRIDE;
@@ -223,7 +224,7 @@
     virtual void checkPlayability() = 0;
     virtual void updateRate() = 0;
     virtual float rate() const = 0;
-    virtual void seekToTime(double time) = 0;
+    virtual void seekToTime(double time, double negativeTolerance, double positiveTolerance) = 0;
     virtual unsigned totalBytes() const = 0;
     virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const = 0;
     virtual double platformMaxTimeSeekable() const = 0;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2013-11-13 18:30:03 UTC (rev 159208)
@@ -142,7 +142,7 @@
     virtual void checkPlayability();
     virtual void updateRate();
     virtual float rate() const;
-    virtual void seekToTime(double time);
+    virtual void seekToTime(double time, double negativeTolerance, double positiveTolerance);
     virtual unsigned totalBytes() const;
     virtual PassRefPtr<TimeRanges> platformBufferedTimeRanges() const;
     virtual double platformMinTimeSeekable() const;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (159207 => 159208)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2013-11-13 18:17:40 UTC (rev 159207)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2013-11-13 18:30:03 UTC (rev 159208)
@@ -644,13 +644,16 @@
     return 0;
 }
 
-void MediaPlayerPrivateAVFoundationObjC::seekToTime(double time)
+void MediaPlayerPrivateAVFoundationObjC::seekToTime(double time, double negativeTolerance, double positiveTolerance)
 {
     // setCurrentTime generates several event callbacks, update afterwards.
     setDelayCallbacks(true);
 
     WebCoreAVFMovieObserver *observer = m_objcObserver.get();
-    [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
+    CMTime cmTime = CMTimeMakeWithSeconds(time, 600);
+    CMTime cmBefore = CMTimeMakeWithSeconds(negativeTolerance, 600);
+    CMTime cmAfter = CMTimeMakeWithSeconds(positiveTolerance, 600);
+    [m_avPlayerItem.get() seekToTime:cmTime toleranceBefore:cmBefore toleranceAfter:cmAfter completionHandler:^(BOOL finished) {
         [observer seekCompleted:finished];
     }];
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to