OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 1627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1638 } else { | 1638 } else { |
1639 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { | 1639 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { |
1640 // 4.8.10.8 | 1640 // 4.8.10.8 |
1641 scheduleTimeupdateEvent(false); | 1641 scheduleTimeupdateEvent(false); |
1642 scheduleEvent(EventTypeNames::waiting); | 1642 scheduleEvent(EventTypeNames::waiting); |
1643 } | 1643 } |
1644 } | 1644 } |
1645 | 1645 |
1646 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { | 1646 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { |
1647 prepareMediaFragmentURI(); | 1647 prepareMediaFragmentURI(); |
1648 | |
1649 m_duration = duration(); | |
1648 scheduleEvent(EventTypeNames::durationchange); | 1650 scheduleEvent(EventTypeNames::durationchange); |
1651 | |
1649 if (isHTMLVideoElement(*this)) | 1652 if (isHTMLVideoElement(*this)) |
1650 scheduleEvent(EventTypeNames::resize); | 1653 scheduleEvent(EventTypeNames::resize); |
1651 scheduleEvent(EventTypeNames::loadedmetadata); | 1654 scheduleEvent(EventTypeNames::loadedmetadata); |
1652 if (hasMediaControls()) | 1655 if (hasMediaControls()) |
1653 mediaControls()->reset(); | 1656 mediaControls()->reset(); |
1654 if (renderer()) | 1657 if (renderer()) |
1655 renderer()->updateFromElement(); | 1658 renderer()->updateFromElement(); |
1656 } | 1659 } |
1657 | 1660 |
1658 bool shouldUpdateDisplayState = false; | 1661 bool shouldUpdateDisplayState = false; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1742 { | 1745 { |
1743 WTF_LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this); | 1746 WTF_LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this); |
1744 if (m_havePreparedToPlay) | 1747 if (m_havePreparedToPlay) |
1745 return; | 1748 return; |
1746 m_havePreparedToPlay = true; | 1749 m_havePreparedToPlay = true; |
1747 | 1750 |
1748 if (m_delayingLoadForPreloadNone) | 1751 if (m_delayingLoadForPreloadNone) |
1749 startDelayedLoad(); | 1752 startDelayedLoad(); |
1750 } | 1753 } |
1751 | 1754 |
1752 void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) | 1755 void HTMLMediaElement::seek(SeekSkipPermission seekSkip, double time, ExceptionS tate& exceptionState) |
1753 { | 1756 { |
1754 WTF_LOG(Media, "HTMLMediaElement::seek(%f)", time); | 1757 WTF_LOG(Media, "HTMLMediaElement::seek(%d, %f)", seekSkip, time); |
1755 | 1758 |
1756 // 4.8.10.9 Seeking | 1759 // 4.8.10.9 Seeking |
1757 | 1760 |
1758 // 1 - If the media element's readyState is HAVE_NOTHING, then raise an Inva lidStateError exception. | 1761 // 1 - If the media element's readyState is HAVE_NOTHING, then raise an Inva lidStateError exception. |
1759 if (m_readyState == HAVE_NOTHING || !m_player) { | 1762 if (m_readyState == HAVE_NOTHING || !m_player) { |
1760 exceptionState.throwDOMException(InvalidStateError, "The element's ready State is HAVE_NOTHING."); | 1763 exceptionState.throwDOMException(InvalidStateError, "The element's ready State is HAVE_NOTHING."); |
1761 return; | 1764 return; |
1762 } | 1765 } |
1763 | 1766 |
1764 // If the media engine has been told to postpone loading data, let it go ahe ad now. | 1767 // If the media engine has been told to postpone loading data, let it go ahe ad now. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1800 | 1803 |
1801 // 7 - If the (possibly now changed) new playback position is not in one of the ranges given in the | 1804 // 7 - If the (possibly now changed) new playback position is not in one of the ranges given in the |
1802 // seekable attribute, then let it be the position in one of the ranges give n in the seekable attribute | 1805 // seekable attribute, then let it be the position in one of the ranges give n in the seekable attribute |
1803 // that is the nearest to the new playback position. ... If there are no ran ges given in the seekable | 1806 // that is the nearest to the new playback position. ... If there are no ran ges given in the seekable |
1804 // attribute then set the seeking IDL attribute to false and abort these ste ps. | 1807 // attribute then set the seeking IDL attribute to false and abort these ste ps. |
1805 RefPtr<TimeRanges> seekableRanges = seekable(); | 1808 RefPtr<TimeRanges> seekableRanges = seekable(); |
1806 | 1809 |
1807 // Short circuit seeking to the current time by just firing the events if no seek is required. | 1810 // Short circuit seeking to the current time by just firing the events if no seek is required. |
1808 // Don't skip calling the media engine if we are in poster mode because a se ek should always | 1811 // Don't skip calling the media engine if we are in poster mode because a se ek should always |
1809 // cancel poster display. | 1812 // cancel poster display. |
1810 bool noSeekRequired = !seekableRanges->length() || (time == now && displayMo de() != Poster); | 1813 if (!seekableRanges->length() |
1811 | 1814 || (seekSkip == SkipAllowed && time == now && displayMode() != Poster)) { |
philipj_slow
2014/06/16 13:26:19
Do you know why we actually need this short circui
acolwell GONE FROM CHROMIUM
2014/06/17 01:24:02
I've never been a fan of this block of code. I'll
philipj_slow
2014/06/17 11:59:06
Thanks, I hope it turns out that the short circuit
acolwell GONE FROM CHROMIUM
2014/06/17 22:39:02
I've removed the short circuiting in https://coder
| |
1812 if (noSeekRequired) { | |
1813 if (time == now) { | 1815 if (time == now) { |
1814 scheduleEvent(EventTypeNames::seeking); | 1816 scheduleEvent(EventTypeNames::seeking); |
1815 if (previousSeekStillPending) | 1817 if (previousSeekStillPending) |
1816 return; | 1818 return; |
1817 // FIXME: There must be a stable state before timeupdate+seeked are dispatched and seeking | 1819 // FIXME: There must be a stable state before timeupdate+seeked are dispatched and seeking |
1818 // is reset to false. See http://crbug.com/266631 | 1820 // is reset to false. See http://crbug.com/266631 |
1819 scheduleTimeupdateEvent(false); | 1821 scheduleTimeupdateEvent(false); |
1820 scheduleEvent(EventTypeNames::seeked); | 1822 scheduleEvent(EventTypeNames::seeked); |
1821 } | 1823 } |
1822 m_seeking = false; | 1824 m_seeking = false; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1920 | 1922 |
1921 return m_cachedTime; | 1923 return m_cachedTime; |
1922 } | 1924 } |
1923 | 1925 |
1924 void HTMLMediaElement::setCurrentTime(double time, ExceptionState& exceptionStat e) | 1926 void HTMLMediaElement::setCurrentTime(double time, ExceptionState& exceptionStat e) |
1925 { | 1927 { |
1926 if (m_mediaController) { | 1928 if (m_mediaController) { |
1927 exceptionState.throwDOMException(InvalidStateError, "The element is slav ed to a MediaController."); | 1929 exceptionState.throwDOMException(InvalidStateError, "The element is slav ed to a MediaController."); |
1928 return; | 1930 return; |
1929 } | 1931 } |
1930 seek(time, exceptionState); | 1932 seek(SkipAllowed, time, exceptionState); |
1931 } | 1933 } |
1932 | 1934 |
1933 double HTMLMediaElement::duration() const | 1935 double HTMLMediaElement::duration() const |
1934 { | 1936 { |
1935 if (!m_player || m_readyState < HAVE_METADATA) | 1937 if (!m_player || m_readyState < HAVE_METADATA) |
1936 return numeric_limits<double>::quiet_NaN(); | 1938 return numeric_limits<double>::quiet_NaN(); |
1937 | 1939 |
1938 // FIXME: Refactor so m_duration is kept current (in both MSE and | 1940 // FIXME: Refactor so m_duration is kept current (in both MSE and |
1939 // non-MSE cases) once we have transitioned from HAVE_NOTHING -> | 1941 // non-MSE cases) once we have transitioned from HAVE_NOTHING -> |
1940 // HAVE_METADATA. Currently, m_duration may be out of date for at least MSE | 1942 // HAVE_METADATA. Currently, m_duration may be out of date for at least MSE |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2047 | 2049 |
2048 void HTMLMediaElement::playInternal() | 2050 void HTMLMediaElement::playInternal() |
2049 { | 2051 { |
2050 WTF_LOG(Media, "HTMLMediaElement::playInternal"); | 2052 WTF_LOG(Media, "HTMLMediaElement::playInternal"); |
2051 | 2053 |
2052 // 4.8.10.9. Playing the media resource | 2054 // 4.8.10.9. Playing the media resource |
2053 if (!m_player || m_networkState == NETWORK_EMPTY) | 2055 if (!m_player || m_networkState == NETWORK_EMPTY) |
2054 scheduleDelayedAction(LoadMediaResource); | 2056 scheduleDelayedAction(LoadMediaResource); |
2055 | 2057 |
2056 if (endedPlayback()) | 2058 if (endedPlayback()) |
2057 seek(0, IGNORE_EXCEPTION); | 2059 seek(SkipAllowed, 0, IGNORE_EXCEPTION); |
2058 | 2060 |
2059 if (m_mediaController) | 2061 if (m_mediaController) |
2060 m_mediaController->bringElementUpToSpeed(this); | 2062 m_mediaController->bringElementUpToSpeed(this); |
2061 | 2063 |
2062 if (m_paused) { | 2064 if (m_paused) { |
2063 m_paused = false; | 2065 m_paused = false; |
2064 invalidateCachedTime(); | 2066 invalidateCachedTime(); |
2065 scheduleEvent(EventTypeNames::play); | 2067 scheduleEvent(EventTypeNames::play); |
2066 | 2068 |
2067 if (m_readyState <= HAVE_CURRENT_DATA) | 2069 if (m_readyState <= HAVE_CURRENT_DATA) |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2775 double now = currentTime(); | 2777 double now = currentTime(); |
2776 double dur = duration(); | 2778 double dur = duration(); |
2777 | 2779 |
2778 // When the current playback position reaches the end of the media resource when the direction of | 2780 // When the current playback position reaches the end of the media resource when the direction of |
2779 // playback is forwards, then the user agent must follow these steps: | 2781 // playback is forwards, then the user agent must follow these steps: |
2780 if (!std::isnan(dur) && dur && now >= dur && m_playbackRate > 0) { | 2782 if (!std::isnan(dur) && dur && now >= dur && m_playbackRate > 0) { |
2781 // If the media element has a loop attribute specified and does not have a current media controller, | 2783 // If the media element has a loop attribute specified and does not have a current media controller, |
2782 if (loop() && !m_mediaController) { | 2784 if (loop() && !m_mediaController) { |
2783 m_sentEndEvent = false; | 2785 m_sentEndEvent = false; |
2784 // then seek to the earliest possible position of the media resourc e and abort these steps. | 2786 // then seek to the earliest possible position of the media resourc e and abort these steps. |
2785 seek(0, IGNORE_EXCEPTION); | 2787 seek(SkipAllowed, 0, IGNORE_EXCEPTION); |
2786 } else { | 2788 } else { |
2787 // If the media element does not have a current media controller, an d the media element | 2789 // If the media element does not have a current media controller, an d the media element |
2788 // has still ended playback, and the direction of playback is still forwards, and paused | 2790 // has still ended playback, and the direction of playback is still forwards, and paused |
2789 // is false, | 2791 // is false, |
2790 if (!m_mediaController && !m_paused) { | 2792 if (!m_mediaController && !m_paused) { |
2791 // changes paused to true and fires a simple event named pause a t the media element. | 2793 // changes paused to true and fires a simple event named pause a t the media element. |
2792 m_paused = true; | 2794 m_paused = true; |
2793 scheduleEvent(EventTypeNames::pause); | 2795 scheduleEvent(EventTypeNames::pause); |
2794 } | 2796 } |
2795 // Queue a task to fire a simple event named ended at the media elem ent. | 2797 // Queue a task to fire a simple event named ended at the media elem ent. |
2796 if (!m_sentEndEvent) { | 2798 if (!m_sentEndEvent) { |
2797 m_sentEndEvent = true; | 2799 m_sentEndEvent = true; |
2798 scheduleEvent(EventTypeNames::ended); | 2800 scheduleEvent(EventTypeNames::ended); |
2799 } | 2801 } |
2800 // If the media element has a current media controller, then report the controller state | 2802 // If the media element has a current media controller, then report the controller state |
2801 // for the media element's current media controller. | 2803 // for the media element's current media controller. |
2802 updateMediaController(); | 2804 updateMediaController(); |
2803 } | 2805 } |
2804 } | 2806 } |
2805 else | 2807 else |
2806 m_sentEndEvent = false; | 2808 m_sentEndEvent = false; |
2807 | 2809 |
2808 updatePlayState(); | 2810 updatePlayState(); |
2809 } | 2811 } |
2810 | 2812 |
2811 void HTMLMediaElement::mediaPlayerDurationChanged() | 2813 void HTMLMediaElement::mediaPlayerDurationChanged() |
2812 { | 2814 { |
2813 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDurationChanged"); | 2815 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDurationChanged"); |
2814 durationChanged(duration()); | 2816 durationChanged(duration(), currentTime() > duration()); |
philipj_slow
2014/06/16 13:26:19
This was already the case, but isn't it weird that
acolwell GONE FROM CHROMIUM
2014/06/17 01:24:02
With the current code this condition should always
philipj_slow
2014/06/17 11:59:06
A FIXME or ASSERT to clarify the current status of
acolwell GONE FROM CHROMIUM
2014/06/17 22:39:02
Done.
| |
2815 } | 2817 } |
2816 | 2818 |
2817 void HTMLMediaElement::durationChanged(double duration) | 2819 void HTMLMediaElement::durationChanged(double duration, bool requestSeek) |
2818 { | 2820 { |
2819 WTF_LOG(Media, "HTMLMediaElement::durationChanged(%f)", duration); | 2821 WTF_LOG(Media, "HTMLMediaElement::durationChanged(%f, %d)", duration, reques tSeek); |
2820 | 2822 |
2821 // Abort if duration unchanged. | 2823 // Abort if duration unchanged. |
2822 if (m_duration == duration) | 2824 if (m_duration == duration) |
2823 return; | 2825 return; |
2824 | 2826 |
2827 double oldDuration = m_duration; | |
2825 m_duration = duration; | 2828 m_duration = duration; |
2829 | |
2830 WTF_LOG(Media, "HTMLMediaElement::durationChanged : %f -> %f", oldDuration, duration); | |
2831 | |
2826 scheduleEvent(EventTypeNames::durationchange); | 2832 scheduleEvent(EventTypeNames::durationchange); |
2827 | 2833 |
2828 if (hasMediaControls()) | 2834 if (hasMediaControls()) |
2829 mediaControls()->reset(); | 2835 mediaControls()->reset(); |
2830 if (renderer()) | 2836 if (renderer()) |
2831 renderer()->updateFromElement(); | 2837 renderer()->updateFromElement(); |
2832 | 2838 |
2833 if (currentTime() > duration) | 2839 if (requestSeek) { |
2834 seek(duration, IGNORE_EXCEPTION); | 2840 // Prevent seek skipping if the duration is getting smaller. The webMedi aPlayer() |
2841 // may be clamping currentTime to duration() so the normal "are we seeki ng to the current location?" | |
2842 // skip check may not be reliable. | |
2843 SeekSkipPermission seekSkip = (duration < oldDuration) ? SkipNotAllowed : SkipAllowed; | |
acolwell GONE FROM CHROMIUM
2014/06/06 23:20:04
This change and ones related to it are needed beca
philipj_slow
2014/06/16 13:26:19
OK, that explains why requestSeek is initialized w
| |
2844 seek(seekSkip, duration, IGNORE_EXCEPTION); | |
2845 } | |
2835 } | 2846 } |
2836 | 2847 |
2837 void HTMLMediaElement::mediaPlayerPlaybackStateChanged() | 2848 void HTMLMediaElement::mediaPlayerPlaybackStateChanged() |
2838 { | 2849 { |
2839 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerPlaybackStateChanged"); | 2850 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerPlaybackStateChanged"); |
2840 | 2851 |
2841 if (!m_player || m_pausedInternal) | 2852 if (!m_player || m_pausedInternal) |
2842 return; | 2853 return; |
2843 | 2854 |
2844 if (m_player->paused()) | 2855 if (m_player->paused()) |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3592 | 3603 |
3593 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE _FUTURE_DATA) | 3604 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE _FUTURE_DATA) |
3594 prepareToPlay(); | 3605 prepareToPlay(); |
3595 } | 3606 } |
3596 | 3607 |
3597 void HTMLMediaElement::applyMediaFragmentURI() | 3608 void HTMLMediaElement::applyMediaFragmentURI() |
3598 { | 3609 { |
3599 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { | 3610 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { |
3600 m_sentEndEvent = false; | 3611 m_sentEndEvent = false; |
3601 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment Start); | 3612 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment Start); |
3602 seek(m_fragmentStartTime, IGNORE_EXCEPTION); | 3613 seek(SkipAllowed, m_fragmentStartTime, IGNORE_EXCEPTION); |
3603 } | 3614 } |
3604 } | 3615 } |
3605 | 3616 |
3606 WebMediaPlayer::CORSMode HTMLMediaElement::corsMode() const | 3617 WebMediaPlayer::CORSMode HTMLMediaElement::corsMode() const |
3607 { | 3618 { |
3608 const AtomicString& crossOriginMode = fastGetAttribute(crossoriginAttr); | 3619 const AtomicString& crossOriginMode = fastGetAttribute(crossoriginAttr); |
3609 if (crossOriginMode.isNull()) | 3620 if (crossOriginMode.isNull()) |
3610 return WebMediaPlayer::CORSModeUnspecified; | 3621 return WebMediaPlayer::CORSModeUnspecified; |
3611 if (equalIgnoringCase(crossOriginMode, "use-credentials")) | 3622 if (equalIgnoringCase(crossOriginMode, "use-credentials")) |
3612 return WebMediaPlayer::CORSModeUseCredentials; | 3623 return WebMediaPlayer::CORSModeUseCredentials; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3654 visitor->trace(m_error); | 3665 visitor->trace(m_error); |
3655 visitor->trace(m_currentSourceNode); | 3666 visitor->trace(m_currentSourceNode); |
3656 visitor->trace(m_nextChildNodeToConsider); | 3667 visitor->trace(m_nextChildNodeToConsider); |
3657 visitor->trace(m_textTracks); | 3668 visitor->trace(m_textTracks); |
3658 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3669 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
3659 WillBeHeapSupplementable<HTMLMediaElement>::trace(visitor); | 3670 WillBeHeapSupplementable<HTMLMediaElement>::trace(visitor); |
3660 HTMLElement::trace(visitor); | 3671 HTMLElement::trace(visitor); |
3661 } | 3672 } |
3662 | 3673 |
3663 } | 3674 } |
OLD | NEW |