Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp

Issue 2425463002: Improve HTMLMediaElement::currentTime() (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 10 matching lines...) Expand all
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "core/html/HTMLMediaElement.h" 27 #include "core/html/HTMLMediaElement.h"
28 28
29 #include "bindings/core/v8/ExceptionState.h" 29 #include "bindings/core/v8/ExceptionState.h"
30 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 30 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
31 #include "bindings/core/v8/Microtask.h"
31 #include "bindings/core/v8/ScriptController.h" 32 #include "bindings/core/v8/ScriptController.h"
32 #include "bindings/core/v8/ScriptEventListener.h" 33 #include "bindings/core/v8/ScriptEventListener.h"
33 #include "bindings/core/v8/ScriptPromiseResolver.h" 34 #include "bindings/core/v8/ScriptPromiseResolver.h"
34 #include "core/HTMLNames.h" 35 #include "core/HTMLNames.h"
35 #include "core/css/MediaList.h" 36 #include "core/css/MediaList.h"
36 #include "core/dom/Attribute.h" 37 #include "core/dom/Attribute.h"
37 #include "core/dom/DOMException.h" 38 #include "core/dom/DOMException.h"
38 #include "core/dom/ElementTraversal.h" 39 #include "core/dom/ElementTraversal.h"
39 #include "core/dom/ElementVisibilityObserver.h" 40 #include "core/dom/ElementVisibilityObserver.h"
40 #include "core/dom/Fullscreen.h" 41 #include "core/dom/Fullscreen.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 #ifndef BLINK_MEDIA_LOG 102 #ifndef BLINK_MEDIA_LOG
102 #define BLINK_MEDIA_LOG DVLOG(3) 103 #define BLINK_MEDIA_LOG DVLOG(3)
103 #endif 104 #endif
104 105
105 #ifndef LOG_MEDIA_EVENTS 106 #ifndef LOG_MEDIA_EVENTS
106 // Default to not logging events because so many are generated they can 107 // Default to not logging events because so many are generated they can
107 // overwhelm the rest of the logging. 108 // overwhelm the rest of the logging.
108 #define LOG_MEDIA_EVENTS 0 109 #define LOG_MEDIA_EVENTS 0
109 #endif 110 #endif
110 111
111 #ifndef LOG_CACHED_TIME_WARNINGS 112 #ifndef LOG_OFFICIAL_TIME_STATUS
112 // Default to not logging warnings about excessive drift in the cached media 113 // Default to not logging status of official time because it adds a fair amount
113 // time because it adds a fair amount of overhead and logging. 114 // of overhead and logging.
114 #define LOG_CACHED_TIME_WARNINGS 0 115 #define LOG_OFFICIAL_TIME_STATUS 0
115 #endif 116 #endif
116 117
117 namespace blink { 118 namespace blink {
118 119
119 using namespace HTMLNames; 120 using namespace HTMLNames;
120 121
121 using WeakMediaElementSet = HeapHashSet<WeakMember<HTMLMediaElement>>; 122 using WeakMediaElementSet = HeapHashSet<WeakMember<HTMLMediaElement>>;
122 using DocumentElementSetMap = 123 using DocumentElementSetMap =
123 HeapHashMap<WeakMember<Document>, Member<WeakMediaElementSet>>; 124 HeapHashMap<WeakMember<Document>, Member<WeakMediaElementSet>>;
124 125
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 m_playbackRate(1.0f), 417 m_playbackRate(1.0f),
417 m_defaultPlaybackRate(1.0f), 418 m_defaultPlaybackRate(1.0f),
418 m_networkState(kNetworkEmpty), 419 m_networkState(kNetworkEmpty),
419 m_readyState(kHaveNothing), 420 m_readyState(kHaveNothing),
420 m_readyStateMaximum(kHaveNothing), 421 m_readyStateMaximum(kHaveNothing),
421 m_volume(1.0f), 422 m_volume(1.0f),
422 m_lastSeekTime(0), 423 m_lastSeekTime(0),
423 m_previousProgressTime(std::numeric_limits<double>::max()), 424 m_previousProgressTime(std::numeric_limits<double>::max()),
424 m_duration(std::numeric_limits<double>::quiet_NaN()), 425 m_duration(std::numeric_limits<double>::quiet_NaN()),
425 m_lastTimeUpdateEventWallTime(0), 426 m_lastTimeUpdateEventWallTime(0),
426 m_lastTimeUpdateEventMovieTime(0), 427 m_lastTimeUpdateEventMediaTime(std::numeric_limits<double>::quiet_NaN()),
427 m_defaultPlaybackStartPosition(0), 428 m_defaultPlaybackStartPosition(0),
428 m_loadState(WaitingForSource), 429 m_loadState(WaitingForSource),
429 m_deferredLoadState(NotDeferred), 430 m_deferredLoadState(NotDeferred),
430 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired), 431 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired),
431 m_webLayer(nullptr), 432 m_webLayer(nullptr),
432 m_displayMode(Unknown), 433 m_displayMode(Unknown),
433 m_cachedTime(std::numeric_limits<double>::quiet_NaN()), 434 m_officialPlaybackPosition(0),
435 m_officialPlaybackPositionNeedsUpdate(true),
434 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), 436 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()),
435 m_pendingActionFlags(0), 437 m_pendingActionFlags(0),
436 m_lockedPendingUserGesture(false), 438 m_lockedPendingUserGesture(false),
437 m_playing(false), 439 m_playing(false),
438 m_shouldDelayLoadEvent(false), 440 m_shouldDelayLoadEvent(false),
439 m_haveFiredLoadedData(false), 441 m_haveFiredLoadedData(false),
440 m_autoplaying(true), 442 m_autoplaying(true),
441 m_muted(false), 443 m_muted(false),
442 m_paused(true), 444 m_paused(true),
443 m_seeking(false), 445 m_seeking(false),
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 "The play() request was interrupted by a new load request."); 844 "The play() request was interrupted by a new load request.");
843 } 845 }
844 846
845 // 4.7 - If seeking is true, set it to false. 847 // 4.7 - If seeking is true, set it to false.
846 m_seeking = false; 848 m_seeking = false;
847 849
848 // 4.8 - Set the current playback position to 0. 850 // 4.8 - Set the current playback position to 0.
849 // Set the official playback position to 0. 851 // Set the official playback position to 0.
850 // If this changed the official playback position, then queue a task 852 // If this changed the official playback position, then queue a task
851 // to fire a simple event named timeupdate at the media element. 853 // to fire a simple event named timeupdate at the media element.
852 // FIXME: Add support for firing this event.
853
854 // 4.9 - Set the initial playback position to 0. 854 // 4.9 - Set the initial playback position to 0.
855 // FIXME: Make this less subtle. The position only becomes 0 because the 855 setOfficialPlaybackPosition(0);
856 // ready state is HAVE_NOTHING. 856 scheduleTimeupdateEvent(false);
857 invalidateCachedTime();
858 857
859 // 4.10 - Set the timeline offset to Not-a-Number (NaN). 858 // 4.10 - Set the timeline offset to Not-a-Number (NaN).
860 // 4.11 - Update the duration attribute to Not-a-Number (NaN). 859 // 4.11 - Update the duration attribute to Not-a-Number (NaN).
861 860
862 cueTimeline().updateActiveCues(0); 861 cueTimeline().updateActiveCues(0);
863 } else if (!m_paused) { 862 } else if (!m_paused) {
864 // TODO(foolip): There is a proposal to always reset the paused state 863 // TODO(foolip): There is a proposal to always reset the paused state
865 // in the media element load algorithm, to avoid a bogus play() promise 864 // in the media element load algorithm, to avoid a bogus play() promise
866 // rejection: https://github.com/whatwg/html/issues/869 865 // rejection: https://github.com/whatwg/html/issues/869
867 // This is where that change would have an effect, and it is measured to 866 // This is where that change would have an effect, and it is measured to
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 // attribute to change to a value lower than kHaveFutureData, then a waiting 1632 // attribute to change to a value lower than kHaveFutureData, then a waiting
1634 // will be fired at the element. 1633 // will be fired at the element.
1635 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) 1634 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData)
1636 scheduleEvent(EventTypeNames::waiting); 1635 scheduleEvent(EventTypeNames::waiting);
1637 1636
1638 // 4.8.10.9 steps 12-14 1637 // 4.8.10.9 steps 12-14
1639 if (m_readyState >= kHaveCurrentData) 1638 if (m_readyState >= kHaveCurrentData)
1640 finishSeek(); 1639 finishSeek();
1641 } else { 1640 } else {
1642 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) { 1641 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) {
1642 // Force an update to official playback position. Automatic updates from
1643 // currentPlaybackPosition() will be blocked while m_readyState remains
1644 // < kHaveFutureData. This blocking is desired after 'waiting' has been
1645 // fired, but its good to update it one final time to accurately reflect
1646 // media time at the moment we ran out of data to play.
1647 setOfficialPlaybackPosition(currentPlaybackPosition());
1648
1643 // 4.8.10.8 1649 // 4.8.10.8
1644 scheduleTimeupdateEvent(false); 1650 scheduleTimeupdateEvent(false);
1645 scheduleEvent(EventTypeNames::waiting); 1651 scheduleEvent(EventTypeNames::waiting);
1646 } 1652 }
1647 } 1653 }
1648 1654
1655 // Once enough of the media data has been fetched to determine the duration of
1656 // the media resource, its dimensions, and other metadata...
1649 if (m_readyState >= kHaveMetadata && oldState < kHaveMetadata) { 1657 if (m_readyState >= kHaveMetadata && oldState < kHaveMetadata) {
1650 createPlaceholderTracksIfNecessary(); 1658 createPlaceholderTracksIfNecessary();
1651 1659
1652 selectInitialTracksIfNecessary(); 1660 selectInitialTracksIfNecessary();
1653 1661
1654 MediaFragmentURIParser fragmentParser(m_currentSrc); 1662 MediaFragmentURIParser fragmentParser(m_currentSrc);
1655 m_fragmentEndTime = fragmentParser.endTime(); 1663 m_fragmentEndTime = fragmentParser.endTime();
1656 1664
1665 // Set the current playback position and the official playback position to
1666 // the earliest possible position.
1667 setOfficialPlaybackPosition(earliestPossiblePosition());
1668
1657 m_duration = duration(); 1669 m_duration = duration();
1658 scheduleEvent(EventTypeNames::durationchange); 1670 scheduleEvent(EventTypeNames::durationchange);
1659 1671
1660 if (isHTMLVideoElement()) 1672 if (isHTMLVideoElement())
1661 scheduleEvent(EventTypeNames::resize); 1673 scheduleEvent(EventTypeNames::resize);
1662 scheduleEvent(EventTypeNames::loadedmetadata); 1674 scheduleEvent(EventTypeNames::loadedmetadata);
1663 1675
1664 bool jumped = false; 1676 bool jumped = false;
1665 if (m_defaultPlaybackStartPosition > 0) { 1677 if (m_defaultPlaybackStartPosition > 0) {
1666 seek(m_defaultPlaybackStartPosition); 1678 seek(m_defaultPlaybackStartPosition);
(...skipping 15 matching lines...) Expand all
1682 if (mediaControls()) 1694 if (mediaControls())
1683 mediaControls()->reset(); 1695 mediaControls()->reset();
1684 if (layoutObject()) 1696 if (layoutObject())
1685 layoutObject()->updateFromElement(); 1697 layoutObject()->updateFromElement();
1686 } 1698 }
1687 1699
1688 bool shouldUpdateDisplayState = false; 1700 bool shouldUpdateDisplayState = false;
1689 1701
1690 if (m_readyState >= kHaveCurrentData && oldState < kHaveCurrentData && 1702 if (m_readyState >= kHaveCurrentData && oldState < kHaveCurrentData &&
1691 !m_haveFiredLoadedData) { 1703 !m_haveFiredLoadedData) {
1704 // Force an update to official playback position to catch non-zero start
1705 // times that were not known at kHaveMetadata, but are known now that the
1706 // first packets have been demuxed.
1707 setOfficialPlaybackPosition(currentPlaybackPosition());
1708
1692 m_haveFiredLoadedData = true; 1709 m_haveFiredLoadedData = true;
1693 shouldUpdateDisplayState = true; 1710 shouldUpdateDisplayState = true;
1694 scheduleEvent(EventTypeNames::loadeddata); 1711 scheduleEvent(EventTypeNames::loadeddata);
1695 setShouldDelayLoadEvent(false); 1712 setShouldDelayLoadEvent(false);
1696 } 1713 }
1697 1714
1698 bool isPotentiallyPlaying = potentiallyPlaying(); 1715 bool isPotentiallyPlaying = potentiallyPlaying();
1699 if (m_readyState == kHaveFutureData && oldState <= kHaveCurrentData && 1716 if (m_readyState == kHaveFutureData && oldState <= kHaveCurrentData &&
1700 tracksAreReady) { 1717 tracksAreReady) {
1701 scheduleEvent(EventTypeNames::canplay); 1718 scheduleEvent(EventTypeNames::canplay);
(...skipping 26 matching lines...) Expand all
1728 // creating a new one in this case. 1745 // creating a new one in this case.
1729 if (!m_autoplayVisibilityObserver) { 1746 if (!m_autoplayVisibilityObserver) {
1730 m_autoplayVisibilityObserver = new ElementVisibilityObserver( 1747 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1731 this, 1748 this,
1732 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, 1749 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1733 wrapWeakPersistent(this))); 1750 wrapWeakPersistent(this)));
1734 m_autoplayVisibilityObserver->start(); 1751 m_autoplayVisibilityObserver->start();
1735 } 1752 }
1736 } else { 1753 } else {
1737 m_paused = false; 1754 m_paused = false;
1738 invalidateCachedTime();
1739 scheduleEvent(EventTypeNames::play); 1755 scheduleEvent(EventTypeNames::play);
1740 scheduleNotifyPlaying(); 1756 scheduleNotifyPlaying();
1741 m_autoplaying = false; 1757 m_autoplaying = false;
1742 } 1758 }
1743 } 1759 }
1744 } 1760 }
1745 1761
1746 scheduleEvent(EventTypeNames::canplaythrough); 1762 scheduleEvent(EventTypeNames::canplaythrough);
1747 1763
1748 shouldUpdateDisplayState = true; 1764 shouldUpdateDisplayState = true;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1804 // m_webMediaPlayer is going out of sync with readystate. 1820 // m_webMediaPlayer is going out of sync with readystate.
1805 // m_webMediaPlayer is cleared but readystate is not set to HAVE_NOTHING. 1821 // m_webMediaPlayer is cleared but readystate is not set to HAVE_NOTHING.
1806 if (!m_webMediaPlayer || m_readyState == kHaveNothing) 1822 if (!m_webMediaPlayer || m_readyState == kHaveNothing)
1807 return; 1823 return;
1808 1824
1809 // Ignore preload none and start load if necessary. 1825 // Ignore preload none and start load if necessary.
1810 setIgnorePreloadNone(); 1826 setIgnorePreloadNone();
1811 1827
1812 // Get the current time before setting m_seeking, m_lastSeekTime is returned 1828 // Get the current time before setting m_seeking, m_lastSeekTime is returned
1813 // once it is set. 1829 // once it is set.
1814 refreshCachedTime(); 1830 double now = currentTime();
1815 // This is needed to avoid getting default playback start position from
1816 // currentTime().
1817 double now = m_cachedTime;
1818 1831
1819 // 3 - If the element's seeking IDL attribute is true, then another instance 1832 // 3 - If the element's seeking IDL attribute is true, then another instance
1820 // of this algorithm is already running. Abort that other instance of the 1833 // of this algorithm is already running. Abort that other instance of the
1821 // algorithm without waiting for the step that it is running to complete. 1834 // algorithm without waiting for the step that it is running to complete.
1822 // Nothing specific to be done here. 1835 // Nothing specific to be done here.
1823 1836
1824 // 4 - Set the seeking IDL attribute to true. 1837 // 4 - Set the seeking IDL attribute to true.
1825 // The flag will be cleared when the engine tells us the time has actually 1838 // The flag will be cleared when the engine tells us the time has actually
1826 // changed. 1839 // changed.
1827 m_seeking = true; 1840 m_seeking = true;
1828 1841
1829 // 6 - If the new playback position is later than the end of the media 1842 // 6 - If the new playback position is later than the end of the media
1830 // resource, then let it be the end of the media resource instead. 1843 // resource, then let it be the end of the media resource instead.
1831 time = std::min(time, duration()); 1844 time = std::min(time, duration());
1832 1845
1833 // 7 - If the new playback position is less than the earliest possible 1846 // 7 - If the new playback position is less than the earliest possible
1834 // position, let it be that position instead. 1847 // position, let it be that position instead.
1835 time = std::max(time, 0.0); 1848 time = std::max(time, earliestPossiblePosition());
1836 1849
1837 // Ask the media engine for the time value in the movie's time scale before 1850 // Ask the media engine for the time value in the movie's time scale before
1838 // comparing with current time. This is necessary because if the seek time is 1851 // comparing with current time. This is necessary because if the seek time is
1839 // not equal to currentTime but the delta is less than the movie's time scale, 1852 // not equal to currentTime but the delta is less than the movie's time scale,
1840 // we will ask the media engine to "seek" to the current movie time, which may 1853 // we will ask the media engine to "seek" to the current movie time, which may
1841 // be a noop and not generate a timechanged callback. This means m_seeking 1854 // be a noop and not generate a timechanged callback. This means m_seeking
1842 // will never be cleared and we will never fire a 'seeked' event. 1855 // will never be cleared and we will never fire a 'seeked' event.
1843 double mediaTime = webMediaPlayer()->mediaTimeForTimeValue(time); 1856 double mediaTime = webMediaPlayer()->mediaTimeForTimeValue(time);
1844 if (time != mediaTime) { 1857 if (time != mediaTime) {
1845 BLINK_MEDIA_LOG << "seek(" << (void*)this << ", " << time 1858 BLINK_MEDIA_LOG << "seek(" << (void*)this << ", " << time
(...skipping 29 matching lines...) Expand all
1875 // 14-17 are handled, if necessary, when the engine signals a readystate 1888 // 14-17 are handled, if necessary, when the engine signals a readystate
1876 // change or otherwise satisfies seek completion and signals a time change. 1889 // change or otherwise satisfies seek completion and signals a time change.
1877 } 1890 }
1878 1891
1879 void HTMLMediaElement::finishSeek() { 1892 void HTMLMediaElement::finishSeek() {
1880 BLINK_MEDIA_LOG << "finishSeek(" << (void*)this << ")"; 1893 BLINK_MEDIA_LOG << "finishSeek(" << (void*)this << ")";
1881 1894
1882 // 14 - Set the seeking IDL attribute to false. 1895 // 14 - Set the seeking IDL attribute to false.
1883 m_seeking = false; 1896 m_seeking = false;
1884 1897
1898 // Force an update to officialPlaybackPosition. Periodic updates generally
1899 // handle this, but may be skipped paused or waiting for data.
1900 setOfficialPlaybackPosition(currentPlaybackPosition());
1901
1885 // 16 - Queue a task to fire a simple event named timeupdate at the element. 1902 // 16 - Queue a task to fire a simple event named timeupdate at the element.
1886 scheduleTimeupdateEvent(false); 1903 scheduleTimeupdateEvent(false);
1887 1904
1888 // 17 - Queue a task to fire a simple event named seeked at the element. 1905 // 17 - Queue a task to fire a simple event named seeked at the element.
1889 scheduleEvent(EventTypeNames::seeked); 1906 scheduleEvent(EventTypeNames::seeked);
1890 1907
1891 setDisplayMode(Video); 1908 setDisplayMode(Video);
1892 } 1909 }
1893 1910
1894 HTMLMediaElement::ReadyState HTMLMediaElement::getReadyState() const { 1911 HTMLMediaElement::ReadyState HTMLMediaElement::getReadyState() const {
1895 return m_readyState; 1912 return m_readyState;
1896 } 1913 }
1897 1914
1898 bool HTMLMediaElement::hasVideo() const { 1915 bool HTMLMediaElement::hasVideo() const {
1899 return webMediaPlayer() && webMediaPlayer()->hasVideo(); 1916 return webMediaPlayer() && webMediaPlayer()->hasVideo();
1900 } 1917 }
1901 1918
1902 bool HTMLMediaElement::hasAudio() const { 1919 bool HTMLMediaElement::hasAudio() const {
1903 return webMediaPlayer() && webMediaPlayer()->hasAudio(); 1920 return webMediaPlayer() && webMediaPlayer()->hasAudio();
1904 } 1921 }
1905 1922
1906 bool HTMLMediaElement::seeking() const { 1923 bool HTMLMediaElement::seeking() const {
1907 return m_seeking; 1924 return m_seeking;
1908 } 1925 }
1909 1926
1910 void HTMLMediaElement::refreshCachedTime() const { 1927 // https://www.w3.org/TR/html51/semantics-embedded-content.html#earliest-possibl e-position
1911 if (!webMediaPlayer() || m_readyState < kHaveMetadata) 1928 // The earliest possible position is not explicitly exposed in the API; it
1912 return; 1929 // corresponds to the start time of the first range in the seekable attribute’s
1930 // TimeRanges object, if any, or the current playback position otherwise.
1931 double HTMLMediaElement::earliestPossiblePosition() const {
1932 TimeRanges* seekableRanges = seekable();
1933 if (seekableRanges && seekableRanges->length() > 0)
1934 return seekableRanges->start(0, ASSERT_NO_EXCEPTION);
1913 1935
1914 m_cachedTime = webMediaPlayer()->currentTime(); 1936 return currentPlaybackPosition();
1915 } 1937 }
1916 1938
1917 void HTMLMediaElement::invalidateCachedTime() { 1939 double HTMLMediaElement::currentPlaybackPosition() const {
1918 BLINK_MEDIA_LOG << "invalidateCachedTime(" << (void*)this << ")"; 1940 // "Official" playback position won't take updates from "current" playback
1919 m_cachedTime = std::numeric_limits<double>::quiet_NaN(); 1941 // position until m_readyState > kHaveMetadata, but other callers (e.g.
1942 // pauseInternal) may still request currentPlaybackPosition at any time.
1943 // From spec: "Media elements have a current playback position, which must
1944 // initially (i.e., in the absence of media data) be zero seconds."
1945 if (m_readyState == kHaveNothing)
1946 return 0;
1947
1948 if (webMediaPlayer())
1949 return webMediaPlayer()->currentTime();
1950
1951 if (m_readyState >= kHaveMetadata) {
1952 LOG(WARNING) << __func__ << " readyState = " << m_readyState
1953 << " but no webMeidaPlayer to provide currentPlaybackPosition";
1954 }
1955
1956 return 0;
1920 } 1957 }
1921 1958
1922 // playback state 1959 double HTMLMediaElement::officialPlaybackPosition() const {
1960 // Hold updates to official playback position while paused or waiting for more
1961 // data. The underlying media player may continue to make small advances in
1962 // currentTime (e.g. as samples in the last rendered audio buffer are played
1963 // played out), but advancing currentTime while paused/waiting sends a mixed
1964 // signal about the state of playback.
1965 bool waitingForData = m_readyState <= kHaveCurrentData;
1966 if (m_officialPlaybackPositionNeedsUpdate && !m_paused && !waitingForData) {
1967 // Internal player position may advance slightly beyond duration because
1968 // many files use imprecise duration. Clamp official position to duration.
1969 double newPosition = std::min(duration(), currentPlaybackPosition());
1970 setOfficialPlaybackPosition(newPosition);
1971 }
1972
1973 #if LOG_OFFICIAL_TIME_STATUS
1974 static const double minCachedDeltaForWarning = 0.01;
1975 double delta =
1976 std::abs(m_officialPlaybackPosition - currentPlaybackPosition());
1977 if (delta > minCachedDeltaForWarning) {
1978 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1979 << ") - WARNING, cached time is " << delta
1980 << "seconds off of media time when paused/waiting";
1981 }
1982 #endif
1983
1984 return m_officialPlaybackPosition;
1985 }
1986
1987 void HTMLMediaElement::setOfficialPlaybackPosition(double position) const {
1988 #if LOG_OFFICIAL_TIME_STATUS
1989 BLINK_MEDIA_LOG << "setOfficialPlaybackPosition(" << (void*)this
1990 << ") was:" << m_officialPlaybackPosition
1991 << " now:" << position;
1992 #endif
1993
1994 m_officialPlaybackPosition = position;
1995
1996 // Once set, official playback position should hold steady until the next
1997 // stable state. We approximate this by using a microtask to mark the
1998 // need for an update after the current (micro)task has completed. When
1999 // needed, the update is applied in the next call to
2000 // officialPlaybackPosition().
2001 m_officialPlaybackPositionNeedsUpdate = false;
2002 Microtask::enqueueMicrotask(
2003 WTF::bind(&HTMLMediaElement::requireOfficialPlaybackPositionUpdate,
2004 wrapWeakPersistent(this)));
2005 }
2006
2007 void HTMLMediaElement::requireOfficialPlaybackPositionUpdate() const {
2008 m_officialPlaybackPositionNeedsUpdate = true;
2009 }
2010
1923 double HTMLMediaElement::currentTime() const { 2011 double HTMLMediaElement::currentTime() const {
1924 if (m_defaultPlaybackStartPosition) 2012 if (m_defaultPlaybackStartPosition)
1925 return m_defaultPlaybackStartPosition; 2013 return m_defaultPlaybackStartPosition;
1926 2014
1927 if (m_readyState == kHaveNothing)
1928 return 0;
1929
1930 if (m_seeking) { 2015 if (m_seeking) {
1931 BLINK_MEDIA_LOG << "currentTime(" << (void*)this 2016 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1932 << ") - seeking, returning " << m_lastSeekTime; 2017 << ") - seeking, returning " << m_lastSeekTime;
1933 return m_lastSeekTime; 2018 return m_lastSeekTime;
1934 } 2019 }
1935 2020
1936 if (!std::isnan(m_cachedTime) && m_paused) { 2021 return officialPlaybackPosition();
1937 #if LOG_CACHED_TIME_WARNINGS
1938 static const double minCachedDeltaForWarning = 0.01;
1939 double delta = m_cachedTime - webMediaPlayer()->currentTime();
1940 if (delta > minCachedDeltaForWarning)
1941 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1942 << ") - WARNING, cached time is " << delta
1943 << "seconds off of media time when paused";
1944 #endif
1945 return m_cachedTime;
1946 }
1947
1948 refreshCachedTime();
1949
1950 return m_cachedTime;
1951 } 2022 }
1952 2023
1953 void HTMLMediaElement::setCurrentTime(double time) { 2024 void HTMLMediaElement::setCurrentTime(double time) {
1954 // If the media element's readyState is kHaveNothing, then set the default 2025 // If the media element's readyState is kHaveNothing, then set the default
1955 // playback start position to that time. 2026 // playback start position to that time.
1956 if (m_readyState == kHaveNothing) { 2027 if (m_readyState == kHaveNothing) {
1957 m_defaultPlaybackStartPosition = time; 2028 m_defaultPlaybackStartPosition = time;
1958 return; 2029 return;
1959 } 2030 }
1960 2031
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2002 2073
2003 double HTMLMediaElement::playbackRate() const { 2074 double HTMLMediaElement::playbackRate() const {
2004 return m_playbackRate; 2075 return m_playbackRate;
2005 } 2076 }
2006 2077
2007 void HTMLMediaElement::setPlaybackRate(double rate) { 2078 void HTMLMediaElement::setPlaybackRate(double rate) {
2008 BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")"; 2079 BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")";
2009 2080
2010 if (m_playbackRate != rate) { 2081 if (m_playbackRate != rate) {
2011 m_playbackRate = rate; 2082 m_playbackRate = rate;
2012 invalidateCachedTime();
2013 scheduleEvent(EventTypeNames::ratechange); 2083 scheduleEvent(EventTypeNames::ratechange);
2014 } 2084 }
2015 2085
2016 updatePlaybackRate(); 2086 updatePlaybackRate();
2017 } 2087 }
2018 2088
2019 HTMLMediaElement::DirectionOfPlayback HTMLMediaElement::getDirectionOfPlayback() 2089 HTMLMediaElement::DirectionOfPlayback HTMLMediaElement::getDirectionOfPlayback()
2020 const { 2090 const {
2021 return m_playbackRate >= 0 ? Forward : Backward; 2091 return m_playbackRate >= 0 ? Forward : Backward;
2022 } 2092 }
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 invokeResourceSelectionAlgorithm(); 2279 invokeResourceSelectionAlgorithm();
2210 2280
2211 // Generally "ended" and "looping" are exclusive. Here, the loop attribute 2281 // Generally "ended" and "looping" are exclusive. Here, the loop attribute
2212 // is ignored to seek back to start in case loop was set after playback 2282 // is ignored to seek back to start in case loop was set after playback
2213 // ended. See http://crbug.com/364442 2283 // ended. See http://crbug.com/364442
2214 if (endedPlayback(LoopCondition::Ignored)) 2284 if (endedPlayback(LoopCondition::Ignored))
2215 seek(0); 2285 seek(0);
2216 2286
2217 if (m_paused) { 2287 if (m_paused) {
2218 m_paused = false; 2288 m_paused = false;
2219 invalidateCachedTime();
2220 scheduleEvent(EventTypeNames::play); 2289 scheduleEvent(EventTypeNames::play);
2221 2290
2222 if (m_readyState <= kHaveCurrentData) 2291 if (m_readyState <= kHaveCurrentData)
2223 scheduleEvent(EventTypeNames::waiting); 2292 scheduleEvent(EventTypeNames::waiting);
2224 else if (m_readyState >= kHaveFutureData) 2293 else if (m_readyState >= kHaveFutureData)
2225 scheduleNotifyPlaying(); 2294 scheduleNotifyPlaying();
2226 } else if (m_readyState >= kHaveFutureData) { 2295 } else if (m_readyState >= kHaveFutureData) {
2227 scheduleResolvePlayPromises(); 2296 scheduleResolvePlayPromises();
2228 } 2297 }
2229 2298
(...skipping 22 matching lines...) Expand all
2252 invokeResourceSelectionAlgorithm(); 2321 invokeResourceSelectionAlgorithm();
2253 2322
2254 m_autoplayHelper->pauseMethodCalled(); 2323 m_autoplayHelper->pauseMethodCalled();
2255 2324
2256 m_autoplaying = false; 2325 m_autoplaying = false;
2257 2326
2258 if (!m_paused) { 2327 if (!m_paused) {
2259 m_paused = true; 2328 m_paused = true;
2260 scheduleTimeupdateEvent(false); 2329 scheduleTimeupdateEvent(false);
2261 scheduleEvent(EventTypeNames::pause); 2330 scheduleEvent(EventTypeNames::pause);
2331
2332 // Force an update to official playback position. Automatic updates from
2333 // currentPlaybackPosition() will be blocked while m_paused = true. This
2334 // blocking is desired while paused, but its good to update it one final
2335 // time to accurately reflect movie time at the moment we paused.
2336 setOfficialPlaybackPosition(currentPlaybackPosition());
2337
2262 scheduleRejectPlayPromises(AbortError); 2338 scheduleRejectPlayPromises(AbortError);
2263 } 2339 }
2264 2340
2265 updatePlayState(); 2341 updatePlayState();
2266 } 2342 }
2267 2343
2268 void HTMLMediaElement::requestRemotePlayback() { 2344 void HTMLMediaElement::requestRemotePlayback() {
2269 if (webMediaPlayer()) 2345 if (webMediaPlayer())
2270 webMediaPlayer()->requestRemotePlayback(); 2346 webMediaPlayer()->requestRemotePlayback();
2271 } 2347 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2436 if (!playbackRate()) 2512 if (!playbackRate())
2437 return; 2513 return;
2438 2514
2439 if (!m_paused && mediaControls()) 2515 if (!m_paused && mediaControls())
2440 mediaControls()->playbackProgressed(); 2516 mediaControls()->playbackProgressed();
2441 2517
2442 cueTimeline().updateActiveCues(currentTime()); 2518 cueTimeline().updateActiveCues(currentTime());
2443 } 2519 }
2444 2520
2445 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) { 2521 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) {
2522 // Per spec, consult current playback position to check for changing time.
2523 double mediaTime = currentPlaybackPosition();
2446 double now = WTF::currentTime(); 2524 double now = WTF::currentTime();
2447 double movieTime = currentTime();
2448 2525
2449 bool haveNotRecentlyFiredTimeupdate = 2526 bool haveNotRecentlyFiredTimeupdate =
2450 (now - m_lastTimeUpdateEventWallTime) >= maxTimeupdateEventFrequency; 2527 (now - m_lastTimeUpdateEventWallTime) >= maxTimeupdateEventFrequency;
2451 bool movieTimeHasProgressed = movieTime != m_lastTimeUpdateEventMovieTime; 2528 bool mediaTimeHasProgressed = mediaTime != m_lastTimeUpdateEventMediaTime;
2452 2529
2453 // Non-periodic timeupdate events must always fire as mandated by the spec, 2530 // Non-periodic timeupdate events must always fire as mandated by the spec,
2454 // otherwise we shouldn't fire duplicate periodic timeupdate events when the 2531 // otherwise we shouldn't fire duplicate periodic timeupdate events when the
2455 // movie time hasn't changed. 2532 // movie time hasn't changed.
2456 if (!periodicEvent || 2533 if (!periodicEvent ||
2457 (haveNotRecentlyFiredTimeupdate && movieTimeHasProgressed)) { 2534 (haveNotRecentlyFiredTimeupdate && mediaTimeHasProgressed)) {
2458 scheduleEvent(EventTypeNames::timeupdate); 2535 scheduleEvent(EventTypeNames::timeupdate);
2459 m_lastTimeUpdateEventWallTime = now; 2536 m_lastTimeUpdateEventWallTime = now;
2460 m_lastTimeUpdateEventMovieTime = movieTime; 2537 m_lastTimeUpdateEventMediaTime = mediaTime;
2461 } 2538 }
2462 } 2539 }
2463 2540
2464 void HTMLMediaElement::togglePlayState() { 2541 void HTMLMediaElement::togglePlayState() {
2465 if (paused()) 2542 if (paused())
2466 play(); 2543 play();
2467 else 2544 else
2468 pause(); 2545 pause();
2469 } 2546 }
2470 2547
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2982 BLINK_MEDIA_LOG << "sourceWasRemoved(" << (void*)this 3059 BLINK_MEDIA_LOG << "sourceWasRemoved(" << (void*)this
2983 << ") - m_currentSourceNode set to 0"; 3060 << ") - m_currentSourceNode set to 0";
2984 } 3061 }
2985 } 3062 }
2986 3063
2987 void HTMLMediaElement::timeChanged() { 3064 void HTMLMediaElement::timeChanged() {
2988 BLINK_MEDIA_LOG << "timeChanged(" << (void*)this << ")"; 3065 BLINK_MEDIA_LOG << "timeChanged(" << (void*)this << ")";
2989 3066
2990 cueTimeline().updateActiveCues(currentTime()); 3067 cueTimeline().updateActiveCues(currentTime());
2991 3068
2992 invalidateCachedTime();
2993
2994 // 4.8.10.9 steps 12-14. Needed if no ReadyState change is associated with the 3069 // 4.8.10.9 steps 12-14. Needed if no ReadyState change is associated with the
2995 // seek. 3070 // seek.
2996 if (m_seeking && m_readyState >= kHaveCurrentData && 3071 if (m_seeking && m_readyState >= kHaveCurrentData &&
2997 !webMediaPlayer()->seeking()) 3072 !webMediaPlayer()->seeking())
2998 finishSeek(); 3073 finishSeek();
2999 3074
3000 // Always call scheduleTimeupdateEvent when the media engine reports a time 3075 // Always call scheduleTimeupdateEvent when the media engine reports a time
3001 // discontinuity, it will only queue a 'timeupdate' event if we haven't 3076 // discontinuity, it will only queue a 'timeupdate' event if we haven't
3002 // already posted one at the current movie time. 3077 // already posted one at the current movie time.
3003 scheduleTimeupdateEvent(false); 3078 scheduleTimeupdateEvent(false);
3004 3079
3005 double now = currentTime(); 3080 double now = currentPlaybackPosition();
3006 double dur = duration(); 3081 double dur = duration();
3007 3082
3008 // When the current playback position reaches the end of the media resource 3083 // When the current playback position reaches the end of the media resource
3009 // when the direction of playback is forwards, then the user agent must follow 3084 // when the direction of playback is forwards, then the user agent must follow
3010 // these steps: 3085 // these steps:
3011 if (!std::isnan(dur) && dur && now >= dur && 3086 if (!std::isnan(dur) && dur && now >= dur &&
3012 getDirectionOfPlayback() == Forward) { 3087 getDirectionOfPlayback() == Forward) {
3013 // If the media element has a loop attribute specified 3088 // If the media element has a loop attribute specified
3014 if (loop()) { 3089 if (loop()) {
3015 // then seek to the earliest possible position of the media resource and 3090 // then seek to the earliest possible position of the media resource and
3016 // abort these steps. 3091 // abort these steps.
3017 seek(0); 3092 seek(earliestPossiblePosition());
3018 } else { 3093 } else {
3019 // If the media element has still ended playback, and the direction of 3094 // If the media element has still ended playback, and the direction of
3020 // playback is still forwards, and paused is false, 3095 // playback is still forwards, and paused is false,
3021 if (!m_paused) { 3096 if (!m_paused) {
3022 // changes paused to true and fires a simple event named pause at the 3097 // changes paused to true and fires a simple event named pause at the
3023 // media element. 3098 // media element.
3024 m_paused = true; 3099 m_paused = true;
3025 scheduleEvent(EventTypeNames::pause); 3100 scheduleEvent(EventTypeNames::pause);
3026 scheduleRejectPlayPromises(AbortError); 3101 scheduleRejectPlayPromises(AbortError);
3027 } 3102 }
3028 // Queue a task to fire a simple event named ended at the media element. 3103 // Queue a task to fire a simple event named ended at the media element.
3029 scheduleEvent(EventTypeNames::ended); 3104 scheduleEvent(EventTypeNames::ended);
3030 } 3105 }
3031 } 3106 }
3032 updatePlayState(); 3107 updatePlayState();
3033 } 3108 }
3034 3109
3035 void HTMLMediaElement::durationChanged() { 3110 void HTMLMediaElement::durationChanged() {
3036 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ")"; 3111 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ")";
3037 // FIXME: Change WebMediaPlayer to convey the currentTime 3112 // If the duration is changed such that the *current playback position* ends
3038 // when the duration change occured. The current WebMediaPlayer 3113 // up being greater than the time of the end of the media resource, then the
3039 // implementations always clamp currentTime() to duration() 3114 // user agent must also seek to the time of the end of the media resource.
3040 // so the requestSeek condition here is always false. 3115 durationChanged(duration(), currentPlaybackPosition() > duration());
3041 durationChanged(duration(), currentTime() > duration());
3042 } 3116 }
3043 3117
3044 void HTMLMediaElement::durationChanged(double duration, bool requestSeek) { 3118 void HTMLMediaElement::durationChanged(double duration, bool requestSeek) {
3045 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ", " << duration 3119 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ", " << duration
3046 << ", " << boolString(requestSeek) << ")"; 3120 << ", " << boolString(requestSeek) << ")";
3047 3121
3048 // Abort if duration unchanged. 3122 // Abort if duration unchanged.
3049 if (m_duration == duration) 3123 if (m_duration == duration)
3050 return; 3124 return;
3051 3125
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
3194 // 4.8.10.8 Playing the media resource 3268 // 4.8.10.8 Playing the media resource
3195 3269
3196 // A media element is said to have ended playback when the element's 3270 // A media element is said to have ended playback when the element's
3197 // readyState attribute is HAVE_METADATA or greater, 3271 // readyState attribute is HAVE_METADATA or greater,
3198 if (m_readyState < kHaveMetadata) 3272 if (m_readyState < kHaveMetadata)
3199 return false; 3273 return false;
3200 3274
3201 // and the current playback position is the end of the media resource and the 3275 // and the current playback position is the end of the media resource and the
3202 // direction of playback is forwards, Either the media element does not have a 3276 // direction of playback is forwards, Either the media element does not have a
3203 // loop attribute specified, 3277 // loop attribute specified,
3204 double now = currentTime(); 3278 double now = currentPlaybackPosition();
3205 if (getDirectionOfPlayback() == Forward) 3279 if (getDirectionOfPlayback() == Forward)
3206 return dur > 0 && now >= dur && 3280 return dur > 0 && now >= dur &&
3207 (loopCondition == LoopCondition::Ignored || !loop()); 3281 (loopCondition == LoopCondition::Ignored || !loop());
3208 3282
3209 // or the current playback position is the earliest possible position and the 3283 // or the current playback position is the earliest possible position and the
3210 // direction of playback is backwards 3284 // direction of playback is backwards
3211 DCHECK_EQ(getDirectionOfPlayback(), Backward); 3285 DCHECK_EQ(getDirectionOfPlayback(), Backward);
3212 return now <= 0; 3286 return now <= earliestPossiblePosition();
3213 } 3287 }
3214 3288
3215 bool HTMLMediaElement::stoppedDueToErrors() const { 3289 bool HTMLMediaElement::stoppedDueToErrors() const {
3216 if (m_readyState >= kHaveMetadata && m_error) { 3290 if (m_readyState >= kHaveMetadata && m_error) {
3217 TimeRanges* seekableRanges = seekable(); 3291 TimeRanges* seekableRanges = seekable();
3218 if (!seekableRanges->contain(currentTime())) 3292 if (!seekableRanges->contain(currentTime()))
3219 return true; 3293 return true;
3220 } 3294 }
3221 3295
3222 return false; 3296 return false;
3223 } 3297 }
3224 3298
3225 void HTMLMediaElement::updatePlayState() { 3299 void HTMLMediaElement::updatePlayState() {
3226 bool isPlaying = webMediaPlayer() && !webMediaPlayer()->paused(); 3300 bool isPlaying = webMediaPlayer() && !webMediaPlayer()->paused();
3227 bool shouldBePlaying = potentiallyPlaying(); 3301 bool shouldBePlaying = potentiallyPlaying();
3228 3302
3229 BLINK_MEDIA_LOG << "updatePlayState(" << (void*)this 3303 BLINK_MEDIA_LOG << "updatePlayState(" << (void*)this
3230 << ") - shouldBePlaying = " << boolString(shouldBePlaying) 3304 << ") - shouldBePlaying = " << boolString(shouldBePlaying)
3231 << ", isPlaying = " << boolString(isPlaying); 3305 << ", isPlaying = " << boolString(isPlaying);
3232 3306
3233 if (shouldBePlaying) { 3307 if (shouldBePlaying) {
3234 setDisplayMode(Video); 3308 setDisplayMode(Video);
3235 invalidateCachedTime();
3236 3309
3237 if (!isPlaying) { 3310 if (!isPlaying) {
3238 // Set rate, muted before calling play in case they were set before the 3311 // Set rate, muted before calling play in case they were set before the
3239 // media engine was setup. The media engine should just stash the rate 3312 // media engine was setup. The media engine should just stash the rate
3240 // and muted values since it isn't already playing. 3313 // and muted values since it isn't already playing.
3241 webMediaPlayer()->setRate(playbackRate()); 3314 webMediaPlayer()->setRate(playbackRate());
3242 updateVolume(); 3315 updateVolume();
3243 webMediaPlayer()->play(); 3316 webMediaPlayer()->play();
3244 m_autoplayHelper->playbackStarted(); 3317 m_autoplayHelper->playbackStarted();
3245 } 3318 }
3246 3319
3247 if (mediaControls()) 3320 if (mediaControls())
3248 mediaControls()->playbackStarted(); 3321 mediaControls()->playbackStarted();
3249 startPlaybackProgressTimer(); 3322 startPlaybackProgressTimer();
3250 m_playing = true; 3323 m_playing = true;
3251 3324
3252 } else { // Should not be playing right now 3325 } else { // Should not be playing right now
3253 if (isPlaying) { 3326 if (isPlaying) {
3254 webMediaPlayer()->pause(); 3327 webMediaPlayer()->pause();
3255 m_autoplayHelper->playbackStopped(); 3328 m_autoplayHelper->playbackStopped();
3256 } 3329 }
3257 3330
3258 refreshCachedTime();
3259
3260 m_playbackProgressTimer.stop(); 3331 m_playbackProgressTimer.stop();
3261 m_playing = false; 3332 m_playing = false;
3262 double time = currentTime(); 3333 double time = currentTime();
3263 if (time > m_lastSeekTime) 3334 if (time > m_lastSeekTime)
3264 addPlayedRange(m_lastSeekTime, time); 3335 addPlayedRange(m_lastSeekTime, time);
3265 3336
3266 if (mediaControls()) 3337 if (mediaControls())
3267 mediaControls()->playbackStopped(); 3338 mediaControls()->playbackStopped();
3268 } 3339 }
3269 3340
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3320 cancelPendingEventsAndCallbacks(); 3391 cancelPendingEventsAndCallbacks();
3321 m_asyncEventQueue->close(); 3392 m_asyncEventQueue->close();
3322 3393
3323 // Clear everything in the Media Element 3394 // Clear everything in the Media Element
3324 clearMediaPlayer(); 3395 clearMediaPlayer();
3325 m_readyState = kHaveNothing; 3396 m_readyState = kHaveNothing;
3326 m_readyStateMaximum = kHaveNothing; 3397 m_readyStateMaximum = kHaveNothing;
3327 setNetworkState(kNetworkEmpty); 3398 setNetworkState(kNetworkEmpty);
3328 setShouldDelayLoadEvent(false); 3399 setShouldDelayLoadEvent(false);
3329 m_currentSourceNode = nullptr; 3400 m_currentSourceNode = nullptr;
3330 invalidateCachedTime(); 3401 m_officialPlaybackPosition = 0;
3402 m_officialPlaybackPositionNeedsUpdate = true;
3331 cueTimeline().updateActiveCues(0); 3403 cueTimeline().updateActiveCues(0);
3332 m_playing = false; 3404 m_playing = false;
3333 m_paused = true; 3405 m_paused = true;
3334 m_seeking = false; 3406 m_seeking = false;
3335 3407
3336 if (layoutObject()) 3408 if (layoutObject())
3337 layoutObject()->updateFromElement(); 3409 layoutObject()->updateFromElement();
3338 3410
3339 stopPeriodicTimers(); 3411 stopPeriodicTimers();
3340 3412
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
3967 ("Media.Controls.Show.Audio", MediaControlsShowMax)); 4039 ("Media.Controls.Show.Audio", MediaControlsShowMax));
3968 return histogram; 4040 return histogram;
3969 } 4041 }
3970 4042
3971 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { 4043 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) {
3972 if (!isVisible) 4044 if (!isVisible)
3973 return; 4045 return;
3974 4046
3975 if (shouldAutoplay()) { 4047 if (shouldAutoplay()) {
3976 m_paused = false; 4048 m_paused = false;
3977 invalidateCachedTime();
3978 scheduleEvent(EventTypeNames::play); 4049 scheduleEvent(EventTypeNames::play);
3979 scheduleNotifyPlaying(); 4050 scheduleNotifyPlaying();
3980 m_autoplaying = false; 4051 m_autoplaying = false;
3981 4052
3982 updatePlayState(); 4053 updatePlayState();
3983 } 4054 }
3984 4055
3985 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay() 4056 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay()
3986 // is never called. The leak comes from either ElementVisibilityObserver or 4057 // is never called. The leak comes from either ElementVisibilityObserver or
3987 // IntersectionObserver. Should keep an eye on it. See 4058 // IntersectionObserver. Should keep an eye on it. See
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
4092 4163
4093 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() 4164 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect()
4094 const { 4165 const {
4095 IntRect result; 4166 IntRect result;
4096 if (LayoutObject* object = m_element->layoutObject()) 4167 if (LayoutObject* object = m_element->layoutObject())
4097 result = object->absoluteBoundingBoxRect(); 4168 result = object->absoluteBoundingBoxRect();
4098 return result; 4169 return result;
4099 } 4170 }
4100 4171
4101 } // namespace blink 4172 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLMediaElement.h ('k') | third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698