Title: [97100] trunk
Revision
97100
Author
jer.no...@apple.com
Date
2011-10-10 15:42:28 -0700 (Mon, 10 Oct 2011)

Log Message

MediaControlSeekButtonElement should support seeking by changing the playback rate.
https://bugs.webkit.org/show_bug.cgi?id=63595

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/video-controls-scanning.html

Add a new property to HTMLMediaElement, supportsScanning(), which returns whether the
element is capable of playing its media at a rate greater than 1x. HTMLMediaElement passes
this call through to MediaPlayer and MediaPlayerPrivate. If this property returns true, the
built-in scanning controls can prefer to scan by changing the playbackRate, rather than by
repeatedly seeking small amounts of time. Unless overridden by specific media engines, this
property defaults to "false".

* html/HTMLMediaElement.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::supportsScanning): Added.  Calls through to MediaPlayer.
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::supportsScanning): Added. Calls through to MediaPlayerPrivate.
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::supportsScanning): Added. Defaults to "false".
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
(WebCore::MediaPlayerPrivateAVFoundation::supportsScanning): Added.
* platform/graphics/mac/MediaPlayerPrivateQTKit.h:
(WebCore::MediaPlayerPrivateQTKit::supportsScanning): Added.

MediaControlSeekButtonElement now queries HTMLMediaElement::supportsScanning() to see if the
media element can implement its seeking behavior by scanning the media at greater than 1x
rate. Note whether the media was playing or paused when the seek begins, so that the playing
state can be restored when seeking ends.  Instead of capturing the mouse after mouseDown,
the seek button now responds to setActive() and begins seeking when the button is active
and stops when it becomes inactive.

Some behaviors have changed: clicking on the seek button no longer causes the media element
to pause; the media will end in the same state it began after the click.  cStepTime has been
eliminated; Clicking the seek button will always skip by at least cSeekTime, or 0.2s.

* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlSeekButtonElement::MediaControlSeekButtonElement): Initialize new
    ivars.
(WebCore::MediaControlSeekButtonElement::defaultEventHandler): Mark mouseDown and mouseUp
    as defaultHandled, so as not to trigger drag start and drag end actions.
(WebCore::MediaControlSeekButtonElement::setActive): Call startTimer or stopTimer based
    on whether the button is active or not.
(WebCore::MediaControlSeekButtonElement::startTimer): Determine whether to scan or skip
    and start the seekTimer.
(WebCore::MediaControlSeekButtonElement::stopTimer): Restore the playing state and
    stop the timer.
(WebCore::MediaControlSeekButtonElement::seekTimerFired): Depending on whether we're
    scanning or skipping, jump ahead or change the playback rate.
* html/shadow/MediaControlElements.h:

LayoutTests:

* media/video-controls-scanning-expected.txt: Added.
* media/video-controls-scanning.html: Added.
* platform/mac/media/video-controls-scanning-expected.txt: Added.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (97099 => 97100)


--- trunk/LayoutTests/ChangeLog	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/LayoutTests/ChangeLog	2011-10-10 22:42:28 UTC (rev 97100)
@@ -1,3 +1,14 @@
+2011-09-20  Jer Noble  <jer.no...@apple.com>
+
+        MediaControlSeekButtonElement should support seeking by changing the playback rate.
+        https://bugs.webkit.org/show_bug.cgi?id=63595
+
+        Reviewed by Eric Carlson.
+
+        * media/video-controls-scanning-expected.txt: Added.
+        * media/video-controls-scanning.html: Added.
+        * platform/mac/media/video-controls-scanning-expected.txt: Added.
+
 2011-10-10  Filip Pizlo  <fpi...@apple.com>
 
         REGRESSIoN (r95399): Web process hangs when opening documents on Google Docs

Modified: trunk/Source/WebCore/ChangeLog (97099 => 97100)


--- trunk/Source/WebCore/ChangeLog	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/ChangeLog	2011-10-10 22:42:28 UTC (rev 97100)
@@ -1,3 +1,58 @@
+2011-09-20  Jer Noble  <jer.no...@apple.com>
+
+        MediaControlSeekButtonElement should support seeking by changing the playback rate.
+        https://bugs.webkit.org/show_bug.cgi?id=63595
+
+        Reviewed by Eric Carlson.
+
+        Test: media/video-controls-scanning.html
+
+        Add a new property to HTMLMediaElement, supportsScanning(), which returns whether the
+        element is capable of playing its media at a rate greater than 1x. HTMLMediaElement passes
+        this call through to MediaPlayer and MediaPlayerPrivate. If this property returns true, the
+        built-in scanning controls can prefer to scan by changing the playbackRate, rather than by
+        repeatedly seeking small amounts of time. Unless overridden by specific media engines, this
+        property defaults to "false".
+
+        * html/HTMLMediaElement.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::supportsScanning): Added.  Calls through to MediaPlayer.
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::supportsScanning): Added. Calls through to MediaPlayerPrivate.
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::supportsScanning): Added. Defaults to "false".
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+        (WebCore::MediaPlayerPrivateAVFoundation::supportsScanning): Added.
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
+        (WebCore::MediaPlayerPrivateQTKit::supportsScanning): Added.
+
+        MediaControlSeekButtonElement now queries HTMLMediaElement::supportsScanning() to see if the
+        media element can implement its seeking behavior by scanning the media at greater than 1x
+        rate. Note whether the media was playing or paused when the seek begins, so that the playing
+        state can be restored when seeking ends.  Instead of capturing the mouse after mouseDown, 
+        the seek button now responds to setActive() and begins seeking when the button is active
+        and stops when it becomes inactive.
+
+        Some behaviors have changed: clicking on the seek button no longer causes the media element
+        to pause; the media will end in the same state it began after the click.  cStepTime has been
+        eliminated; Clicking the seek button will always skip by at least cSeekTime, or 0.2s.
+
+        * html/shadow/MediaControlElements.cpp:
+        (WebCore::MediaControlSeekButtonElement::MediaControlSeekButtonElement): Initialize new 
+            ivars.
+        (WebCore::MediaControlSeekButtonElement::defaultEventHandler): Mark mouseDown and mouseUp
+            as defaultHandled, so as not to trigger drag start and drag end actions.
+        (WebCore::MediaControlSeekButtonElement::setActive): Call startTimer or stopTimer based
+            on whether the button is active or not.
+        (WebCore::MediaControlSeekButtonElement::startTimer): Determine whether to scan or skip
+            and start the seekTimer.
+        (WebCore::MediaControlSeekButtonElement::stopTimer): Restore the playing state and
+            stop the timer.
+        (WebCore::MediaControlSeekButtonElement::seekTimerFired): Depending on whether we're 
+            scanning or skipping, jump ahead or change the playback rate.
+        * html/shadow/MediaControlElements.h:
+
 2011-10-10  Mark Hahnenberg  <mhahnenb...@apple.com>
 
         Remove getCallDataVirtual methods

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (97099 => 97100)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2011-10-10 22:42:28 UTC (rev 97100)
@@ -1250,6 +1250,11 @@
     return m_player ? m_player->supportsSave() : false;
 }
 
+bool HTMLMediaElement::supportsScanning() const
+{
+    return m_player ? m_player->supportsScanning() : false;
+}
+
 void HTMLMediaElement::prepareToPlay()
 {
     LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this);

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (97099 => 97100)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -73,6 +73,7 @@
     virtual bool supportsFullscreen() const { return false; };
 
     virtual bool supportsSave() const;
+    virtual bool supportsScanning() const;
     
     PlatformMedia platformMedia() const;
 #if USE(ACCELERATED_COMPOSITING)

Modified: trunk/Source/WebCore/html/shadow/MediaControlElements.cpp (97099 => 97100)


--- trunk/Source/WebCore/html/shadow/MediaControlElements.cpp	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/html/shadow/MediaControlElements.cpp	2011-10-10 22:42:28 UTC (rev 97100)
@@ -64,9 +64,10 @@
 }
 
 // FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in.
-static const float cSeekRepeatDelay = 0.1f;
-static const float cStepTime = 0.07f;
-static const float cSeekTime = 0.2f;
+static const float cSkipRepeatDelay = 0.1f;
+static const float cSkipTime = 0.2f;
+static const float cScanRepeatDelay = 1.5f;
+static const float cScanMaximumRate = 8;
 
 // ----------------------------
 
@@ -535,59 +536,83 @@
 
 inline MediaControlSeekButtonElement::MediaControlSeekButtonElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType)
     : MediaControlInputElement(mediaElement, displayType)
-    , m_seeking(false)
-    , m_capturing(false)
+    , m_actionOnStop(Nothing)
+    , m_seekType(Skip)
     , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
 {
 }
 
 void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
 {
-    if (event->type() == eventNames().mousedownEvent) {
-        if (Frame* frame = document()->frame()) {
-            m_capturing = true;
-            frame->eventHandler()->setCapturingMouseEventsNode(this);
-        }
-        mediaElement()->pause();
-        m_seekTimer.startRepeating(cSeekRepeatDelay);
+    // Set the mousedown and mouseup events as defaultHandled so they
+    // do not trigger drag start or end actions in MediaControlPanelElement.
+    if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
         event->setDefaultHandled();
-    } else if (event->type() == eventNames().mouseupEvent) {
-        if (m_capturing)
-            if (Frame* frame = document()->frame()) {
-                m_capturing = false;
-                frame->eventHandler()->setCapturingMouseEventsNode(0);
-            }
-        ExceptionCode ec;
-        if (m_seeking || m_seekTimer.isActive()) {
-            if (!m_seeking) {
-                float stepTime = isForwardButton() ? cStepTime : -cStepTime;
-                mediaElement()->setCurrentTime(mediaElement()->currentTime() + stepTime, ec);
-            }
-            m_seekTimer.stop();
-            m_seeking = false;
-            event->setDefaultHandled();
-        }
-    }
-    HTMLInputElement::defaultEventHandler(event);
 }
 
-void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
+void MediaControlSeekButtonElement::setActive(bool flag, bool pause)
 {
-    ExceptionCode ec;
-    m_seeking = true;
-    float seekTime = isForwardButton() ? cSeekTime : -cSeekTime;
-    mediaElement()->setCurrentTime(mediaElement()->currentTime() + seekTime, ec);
+    if (flag == active())
+        return;
+
+    if (flag)
+        startTimer();
+    else
+        stopTimer();
+
+    MediaControlInputElement::setActive(flag, pause);
 }
 
-void MediaControlSeekButtonElement::detach()
+void MediaControlSeekButtonElement::startTimer()
 {
-    if (m_capturing) {
-        if (Frame* frame = document()->frame())
-            frame->eventHandler()->setCapturingMouseEventsNode(0);      
+    m_seekType = mediaElement()->supportsScanning() ? Scan : Skip;
+
+    if (m_seekType == Skip) {
+        // Seeking by skipping requires the video to be paused during seeking.
+        m_actionOnStop = mediaElement()->isPlaying() ? Play : Nothing;
+        mediaElement()->pause();
+    } else {
+        // Seeking by scanning requires the video to be playing during seeking.
+        m_actionOnStop = mediaElement()->paused() ? Pause : Nothing;
+        mediaElement()->play();
+        mediaElement()->setPlaybackRate(nextRate());
     }
-    MediaControlInputElement::detach();
+
+    m_seekTimer.start(0, m_seekType == Skip ? cSkipRepeatDelay : cScanRepeatDelay);
 }
 
+void MediaControlSeekButtonElement::stopTimer()
+{
+    if (m_seekType == Scan)
+        mediaElement()->setPlaybackRate(mediaElement()->defaultPlaybackRate());
+
+    if (m_actionOnStop == Play)
+        mediaElement()->play();
+    else if (m_actionOnStop == Pause)
+        mediaElement()->pause();
+
+    if (m_seekTimer.isActive())
+        m_seekTimer.stop();
+}
+
+float MediaControlSeekButtonElement::nextRate() const
+{
+    float rate = std::min(cScanMaximumRate, fabsf(mediaElement()->playbackRate() * 2));
+    if (!isForwardButton())
+        rate *= -1;
+    return rate;
+}
+
+void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
+{
+    if (m_seekType == Skip) {
+        ExceptionCode ec;
+        float skipTime = isForwardButton() ? cSkipTime : -cSkipTime;
+        mediaElement()->setCurrentTime(mediaElement()->currentTime() + skipTime, ec);
+    } else
+        mediaElement()->setPlaybackRate(nextRate());
+}
+
 // ----------------------------
 
 inline MediaControlSeekForwardButtonElement::MediaControlSeekForwardButtonElement(HTMLMediaElement* mediaElement)

Modified: trunk/Source/WebCore/html/shadow/MediaControlElements.h (97099 => 97100)


--- trunk/Source/WebCore/html/shadow/MediaControlElements.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/html/shadow/MediaControlElements.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -259,12 +259,17 @@
 
 private:
     virtual bool isForwardButton() const = 0;
+    virtual void setActive(bool /*flag*/ = true, bool /*pause*/ = false);
 
-    virtual void detach();
+    void startTimer();
+    void stopTimer();
+    float nextRate() const;
     void seekTimerFired(Timer<MediaControlSeekButtonElement>*);
 
-    bool m_seeking;
-    bool m_capturing;
+    enum ActionType { Nothing, Play, Pause };
+    ActionType m_actionOnStop;
+    enum SeekType { Skip, Scan };
+    SeekType m_seekType;
     Timer<MediaControlSeekButtonElement> m_seekTimer;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (97099 => 97100)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2011-10-10 22:42:28 UTC (rev 97100)
@@ -494,6 +494,11 @@
     return m_private->supportsSave();
 }
 
+bool MediaPlayer::supportsScanning() const
+{
+    return m_private->supportsScanning();
+}
+
 IntSize MediaPlayer::naturalSize()
 {
     return m_private->naturalSize();

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (97099 => 97100)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -190,6 +190,7 @@
 
     bool supportsFullscreen() const;
     bool supportsSave() const;
+    bool supportsScanning() const;
     PlatformMedia platformMedia() const;
 #if USE(ACCELERATED_COMPOSITING)
     PlatformLayer* platformLayer() const;

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (97099 => 97100)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -56,6 +56,7 @@
 
     virtual bool supportsFullscreen() const { return false; }
     virtual bool supportsSave() const { return false; }
+    virtual bool supportsScanning() const { return false; }
 
     virtual IntSize naturalSize() const = 0;
 

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -155,6 +155,7 @@
     virtual float mediaTimeForTimeValue(float) const = 0;
 
     virtual bool supportsFullscreen() const;
+    virtual bool supportsScanning() const { return true; }
 
     // Required interfaces for concrete derived classes.
     virtual void createAVAssetForURL(const String&) = 0;

Modified: trunk/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h (97099 => 97100)


--- trunk/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h	2011-10-10 22:41:01 UTC (rev 97099)
+++ trunk/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h	2011-10-10 22:42:28 UTC (rev 97100)
@@ -93,6 +93,7 @@
     bool hasVideo() const;
     bool hasAudio() const;
     bool supportsFullscreen() const;
+    virtual bool supportsScanning() const { return true; }
     
     void load(const String& url);
     void cancelLoad();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to