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

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

Issue 2425463002: Improve HTMLMediaElement::currentTime() (Closed)
Patch Set: Fix test failure (update start position upon loadeddata) 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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 "The play() request was interrupted by a new load request."); 839 "The play() request was interrupted by a new load request.");
838 } 840 }
839 841
840 // 4.7 - If seeking is true, set it to false. 842 // 4.7 - If seeking is true, set it to false.
841 m_seeking = false; 843 m_seeking = false;
842 844
843 // 4.8 - Set the current playback position to 0. 845 // 4.8 - Set the current playback position to 0.
844 // Set the official playback position to 0. 846 // Set the official playback position to 0.
845 // If this changed the official playback position, then queue a task 847 // If this changed the official playback position, then queue a task
846 // to fire a simple event named timeupdate at the media element. 848 // to fire a simple event named timeupdate at the media element.
847 // FIXME: Add support for firing this event.
848
849 // 4.9 - Set the initial playback position to 0. 849 // 4.9 - Set the initial playback position to 0.
850 // FIXME: Make this less subtle. The position only becomes 0 because the 850 setOfficialPlaybackPosition(0);
851 // ready state is HAVE_NOTHING. 851 scheduleTimeupdateEvent(false);
852 invalidateCachedTime();
853 852
854 // 4.10 - Set the timeline offset to Not-a-Number (NaN). 853 // 4.10 - Set the timeline offset to Not-a-Number (NaN).
855 // 4.11 - Update the duration attribute to Not-a-Number (NaN). 854 // 4.11 - Update the duration attribute to Not-a-Number (NaN).
856 855
857 cueTimeline().updateActiveCues(0); 856 cueTimeline().updateActiveCues(0);
858 } else if (!m_paused) { 857 } else if (!m_paused) {
859 // TODO(foolip): There is a proposal to always reset the paused state 858 // TODO(foolip): There is a proposal to always reset the paused state
860 // in the media element load algorithm, to avoid a bogus play() promise 859 // in the media element load algorithm, to avoid a bogus play() promise
861 // rejection: https://github.com/whatwg/html/issues/869 860 // rejection: https://github.com/whatwg/html/issues/869
862 // This is where that change would have an effect, and it is measured to 861 // 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
1628 // attribute to change to a value lower than kHaveFutureData, then a waiting 1627 // attribute to change to a value lower than kHaveFutureData, then a waiting
1629 // will be fired at the element. 1628 // will be fired at the element.
1630 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) 1629 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData)
1631 scheduleEvent(EventTypeNames::waiting); 1630 scheduleEvent(EventTypeNames::waiting);
1632 1631
1633 // 4.8.10.9 steps 12-14 1632 // 4.8.10.9 steps 12-14
1634 if (m_readyState >= kHaveCurrentData) 1633 if (m_readyState >= kHaveCurrentData)
1635 finishSeek(); 1634 finishSeek();
1636 } else { 1635 } else {
1637 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) { 1636 if (wasPotentiallyPlaying && m_readyState < kHaveFutureData) {
1637 // Force an update to official playback position. Automatic updates from
1638 // currentPlaybackPosition() will be blocked while m_readyState remains
1639 // < kHaveFutureData. This blocking is desired after 'waiting' has been
1640 // fired, but its good to update it one final time to accurately reflect
1641 // media time at the moment we ran out of data to play.
1642 setOfficialPlaybackPosition(currentPlaybackPosition());
1643
1638 // 4.8.10.8 1644 // 4.8.10.8
1639 scheduleTimeupdateEvent(false); 1645 scheduleTimeupdateEvent(false);
1640 scheduleEvent(EventTypeNames::waiting); 1646 scheduleEvent(EventTypeNames::waiting);
1641 } 1647 }
1642 } 1648 }
1643 1649
1650 // Once enough of the media data has been fetched to determine the duration of
1651 // the media resource, its dimensions, and other metadata...
1644 if (m_readyState >= kHaveMetadata && oldState < kHaveMetadata) { 1652 if (m_readyState >= kHaveMetadata && oldState < kHaveMetadata) {
1645 createPlaceholderTracksIfNecessary(); 1653 createPlaceholderTracksIfNecessary();
1646 1654
1647 selectInitialTracksIfNecessary(); 1655 selectInitialTracksIfNecessary();
1648 1656
1649 MediaFragmentURIParser fragmentParser(m_currentSrc); 1657 MediaFragmentURIParser fragmentParser(m_currentSrc);
1650 m_fragmentEndTime = fragmentParser.endTime(); 1658 m_fragmentEndTime = fragmentParser.endTime();
1651 1659
1660 // Set the current playback position and the official playback position to
1661 // the earliest possible position.
1662 setOfficialPlaybackPosition(earliestPossiblePosition());
1663
1652 m_duration = duration(); 1664 m_duration = duration();
1653 scheduleEvent(EventTypeNames::durationchange); 1665 scheduleEvent(EventTypeNames::durationchange);
1654 1666
1655 if (isHTMLVideoElement()) 1667 if (isHTMLVideoElement())
1656 scheduleEvent(EventTypeNames::resize); 1668 scheduleEvent(EventTypeNames::resize);
1657 scheduleEvent(EventTypeNames::loadedmetadata); 1669 scheduleEvent(EventTypeNames::loadedmetadata);
1658 1670
1659 bool jumped = false; 1671 bool jumped = false;
1660 if (m_defaultPlaybackStartPosition > 0) { 1672 if (m_defaultPlaybackStartPosition > 0) {
1661 seek(m_defaultPlaybackStartPosition); 1673 seek(m_defaultPlaybackStartPosition);
(...skipping 15 matching lines...) Expand all
1677 if (mediaControls()) 1689 if (mediaControls())
1678 mediaControls()->reset(); 1690 mediaControls()->reset();
1679 if (layoutObject()) 1691 if (layoutObject())
1680 layoutObject()->updateFromElement(); 1692 layoutObject()->updateFromElement();
1681 } 1693 }
1682 1694
1683 bool shouldUpdateDisplayState = false; 1695 bool shouldUpdateDisplayState = false;
1684 1696
1685 if (m_readyState >= kHaveCurrentData && oldState < kHaveCurrentData && 1697 if (m_readyState >= kHaveCurrentData && oldState < kHaveCurrentData &&
1686 !m_haveFiredLoadedData) { 1698 !m_haveFiredLoadedData) {
1699 // Force an update to official playback position to catch non-zero start
1700 // times that were not known at kHaveMetadata, but are known now that the
1701 // first packets have been demuxed.
1702 setOfficialPlaybackPosition(currentPlaybackPosition());
1703
1687 m_haveFiredLoadedData = true; 1704 m_haveFiredLoadedData = true;
1688 shouldUpdateDisplayState = true; 1705 shouldUpdateDisplayState = true;
1689 scheduleEvent(EventTypeNames::loadeddata); 1706 scheduleEvent(EventTypeNames::loadeddata);
1690 setShouldDelayLoadEvent(false); 1707 setShouldDelayLoadEvent(false);
1691 } 1708 }
1692 1709
1693 bool isPotentiallyPlaying = potentiallyPlaying(); 1710 bool isPotentiallyPlaying = potentiallyPlaying();
1694 if (m_readyState == kHaveFutureData && oldState <= kHaveCurrentData && 1711 if (m_readyState == kHaveFutureData && oldState <= kHaveCurrentData &&
1695 tracksAreReady) { 1712 tracksAreReady) {
1696 scheduleEvent(EventTypeNames::canplay); 1713 scheduleEvent(EventTypeNames::canplay);
(...skipping 26 matching lines...) Expand all
1723 // creating a new one in this case. 1740 // creating a new one in this case.
1724 if (!m_autoplayVisibilityObserver) { 1741 if (!m_autoplayVisibilityObserver) {
1725 m_autoplayVisibilityObserver = new ElementVisibilityObserver( 1742 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1726 this, 1743 this,
1727 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, 1744 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1728 wrapWeakPersistent(this))); 1745 wrapWeakPersistent(this)));
1729 m_autoplayVisibilityObserver->start(); 1746 m_autoplayVisibilityObserver->start();
1730 } 1747 }
1731 } else { 1748 } else {
1732 m_paused = false; 1749 m_paused = false;
1733 invalidateCachedTime();
1734 scheduleEvent(EventTypeNames::play); 1750 scheduleEvent(EventTypeNames::play);
1735 scheduleNotifyPlaying(); 1751 scheduleNotifyPlaying();
1736 m_autoplaying = false; 1752 m_autoplaying = false;
1737 } 1753 }
1738 } 1754 }
1739 } 1755 }
1740 1756
1741 scheduleEvent(EventTypeNames::canplaythrough); 1757 scheduleEvent(EventTypeNames::canplaythrough);
1742 1758
1743 shouldUpdateDisplayState = true; 1759 shouldUpdateDisplayState = true;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 // m_webMediaPlayer is going out of sync with readystate. 1815 // m_webMediaPlayer is going out of sync with readystate.
1800 // m_webMediaPlayer is cleared but readystate is not set to HAVE_NOTHING. 1816 // m_webMediaPlayer is cleared but readystate is not set to HAVE_NOTHING.
1801 if (!m_webMediaPlayer || m_readyState == kHaveNothing) 1817 if (!m_webMediaPlayer || m_readyState == kHaveNothing)
1802 return; 1818 return;
1803 1819
1804 // Ignore preload none and start load if necessary. 1820 // Ignore preload none and start load if necessary.
1805 setIgnorePreloadNone(); 1821 setIgnorePreloadNone();
1806 1822
1807 // Get the current time before setting m_seeking, m_lastSeekTime is returned 1823 // Get the current time before setting m_seeking, m_lastSeekTime is returned
1808 // once it is set. 1824 // once it is set.
1809 refreshCachedTime(); 1825 double now = currentTime();
1810 // This is needed to avoid getting default playback start position from
1811 // currentTime().
1812 double now = m_cachedTime;
1813 1826
1814 // 3 - If the element's seeking IDL attribute is true, then another instance 1827 // 3 - If the element's seeking IDL attribute is true, then another instance
1815 // of this algorithm is already running. Abort that other instance of the 1828 // of this algorithm is already running. Abort that other instance of the
1816 // algorithm without waiting for the step that it is running to complete. 1829 // algorithm without waiting for the step that it is running to complete.
1817 // Nothing specific to be done here. 1830 // Nothing specific to be done here.
1818 1831
1819 // 4 - Set the seeking IDL attribute to true. 1832 // 4 - Set the seeking IDL attribute to true.
1820 // The flag will be cleared when the engine tells us the time has actually 1833 // The flag will be cleared when the engine tells us the time has actually
1821 // changed. 1834 // changed.
1822 m_seeking = true; 1835 m_seeking = true;
1823 1836
1824 // 6 - If the new playback position is later than the end of the media 1837 // 6 - If the new playback position is later than the end of the media
1825 // resource, then let it be the end of the media resource instead. 1838 // resource, then let it be the end of the media resource instead.
1826 time = std::min(time, duration()); 1839 time = std::min(time, duration());
1827 1840
1828 // 7 - If the new playback position is less than the earliest possible 1841 // 7 - If the new playback position is less than the earliest possible
1829 // position, let it be that position instead. 1842 // position, let it be that position instead.
1830 time = std::max(time, 0.0); 1843 time = std::max(time, earliestPossiblePosition());
1831 1844
1832 // Ask the media engine for the time value in the movie's time scale before 1845 // Ask the media engine for the time value in the movie's time scale before
1833 // comparing with current time. This is necessary because if the seek time is 1846 // comparing with current time. This is necessary because if the seek time is
1834 // not equal to currentTime but the delta is less than the movie's time scale, 1847 // not equal to currentTime but the delta is less than the movie's time scale,
1835 // we will ask the media engine to "seek" to the current movie time, which may 1848 // we will ask the media engine to "seek" to the current movie time, which may
1836 // be a noop and not generate a timechanged callback. This means m_seeking 1849 // be a noop and not generate a timechanged callback. This means m_seeking
1837 // will never be cleared and we will never fire a 'seeked' event. 1850 // will never be cleared and we will never fire a 'seeked' event.
1838 double mediaTime = webMediaPlayer()->mediaTimeForTimeValue(time); 1851 double mediaTime = webMediaPlayer()->mediaTimeForTimeValue(time);
1839 if (time != mediaTime) { 1852 if (time != mediaTime) {
1840 BLINK_MEDIA_LOG << "seek(" << (void*)this << ", " << time 1853 BLINK_MEDIA_LOG << "seek(" << (void*)this << ", " << time
(...skipping 29 matching lines...) Expand all
1870 // 14-17 are handled, if necessary, when the engine signals a readystate 1883 // 14-17 are handled, if necessary, when the engine signals a readystate
1871 // change or otherwise satisfies seek completion and signals a time change. 1884 // change or otherwise satisfies seek completion and signals a time change.
1872 } 1885 }
1873 1886
1874 void HTMLMediaElement::finishSeek() { 1887 void HTMLMediaElement::finishSeek() {
1875 BLINK_MEDIA_LOG << "finishSeek(" << (void*)this << ")"; 1888 BLINK_MEDIA_LOG << "finishSeek(" << (void*)this << ")";
1876 1889
1877 // 14 - Set the seeking IDL attribute to false. 1890 // 14 - Set the seeking IDL attribute to false.
1878 m_seeking = false; 1891 m_seeking = false;
1879 1892
1893 // Force an update to officialPlaybackPosition. Periodic updates generally
1894 // handle this, but may be skipped paused or waiting for data.
1895 setOfficialPlaybackPosition(currentPlaybackPosition());
1896
1880 // 16 - Queue a task to fire a simple event named timeupdate at the element. 1897 // 16 - Queue a task to fire a simple event named timeupdate at the element.
1881 scheduleTimeupdateEvent(false); 1898 scheduleTimeupdateEvent(false);
1882 1899
1883 // 17 - Queue a task to fire a simple event named seeked at the element. 1900 // 17 - Queue a task to fire a simple event named seeked at the element.
1884 scheduleEvent(EventTypeNames::seeked); 1901 scheduleEvent(EventTypeNames::seeked);
1885 1902
1886 setDisplayMode(Video); 1903 setDisplayMode(Video);
1887 } 1904 }
1888 1905
1889 HTMLMediaElement::ReadyState HTMLMediaElement::getReadyState() const { 1906 HTMLMediaElement::ReadyState HTMLMediaElement::getReadyState() const {
1890 return m_readyState; 1907 return m_readyState;
1891 } 1908 }
1892 1909
1893 bool HTMLMediaElement::hasVideo() const { 1910 bool HTMLMediaElement::hasVideo() const {
1894 return webMediaPlayer() && webMediaPlayer()->hasVideo(); 1911 return webMediaPlayer() && webMediaPlayer()->hasVideo();
1895 } 1912 }
1896 1913
1897 bool HTMLMediaElement::hasAudio() const { 1914 bool HTMLMediaElement::hasAudio() const {
1898 return webMediaPlayer() && webMediaPlayer()->hasAudio(); 1915 return webMediaPlayer() && webMediaPlayer()->hasAudio();
1899 } 1916 }
1900 1917
1901 bool HTMLMediaElement::seeking() const { 1918 bool HTMLMediaElement::seeking() const {
1902 return m_seeking; 1919 return m_seeking;
1903 } 1920 }
1904 1921
1905 void HTMLMediaElement::refreshCachedTime() const { 1922 // https://www.w3.org/TR/html51/semantics-embedded-content.html#earliest-possibl e-position
1906 if (!webMediaPlayer() || m_readyState < kHaveMetadata) 1923 // The earliest possible position is not explicitly exposed in the API; it
1907 return; 1924 // corresponds to the start time of the first range in the seekable attribute’s
1925 // TimeRanges object, if any, or the current playback position otherwise.
1926 double HTMLMediaElement::earliestPossiblePosition() const {
1927 TimeRanges* seekableRanges = seekable();
1928 if (seekableRanges && seekableRanges->length() > 0)
1929 return seekableRanges->start(0, ASSERT_NO_EXCEPTION);
1908 1930
1909 m_cachedTime = webMediaPlayer()->currentTime(); 1931 return currentPlaybackPosition();
1910 } 1932 }
1911 1933
1912 void HTMLMediaElement::invalidateCachedTime() { 1934 double HTMLMediaElement::currentPlaybackPosition() const {
1913 BLINK_MEDIA_LOG << "invalidateCachedTime(" << (void*)this << ")"; 1935 // "Official" playback position won't take updates from "current" playback
1914 m_cachedTime = std::numeric_limits<double>::quiet_NaN(); 1936 // position until m_readyState > kHaveMetadata, but other callers (e.g.
1937 // pauseInternal) may still request currentPlaybackPosition at any time.
1938 // From spec: "Media elements have a current playback position, which must
1939 // initially (i.e., in the absence of media data) be zero seconds."
1940 if (m_readyState == kHaveNothing)
1941 return 0;
1942
1943 if (webMediaPlayer())
1944 return webMediaPlayer()->currentTime();
1945
1946 if (m_readyState >= kHaveMetadata) {
1947 LOG(WARNING) << __func__ << " readyState = " << m_readyState
1948 << " but no webMeidaPlayer to provide currentPlaybackPosition";
1949 }
1950
1951 return 0;
1915 } 1952 }
1916 1953
1917 // playback state 1954 double HTMLMediaElement::officialPlaybackPosition() const {
1955 // Hold updates to official playback position while paused or waiting for more
1956 // data. The underlying media player may continue to make small advances in
1957 // currentTime (e.g. as samples in the last rendered audio buffer are played
1958 // played out), but advancing currentTime while paused/waiting sends a mixed
1959 // signal about the state of playback.
1960 bool waitingForData = m_readyState <= kHaveCurrentData;
1961 if (m_officialPlaybackPositionNeedsUpdate && !m_paused && !waitingForData) {
1962 // Internal player position may advance slightly beyond duration because
1963 // many files use imprecise duration. Clamp official position to duration.
1964 double newPosition = std::min(duration(), currentPlaybackPosition());
1965 setOfficialPlaybackPosition(newPosition);
1966 }
1967
1968 #if LOG_OFFICIAL_TIME_STATUS
1969 static const double minCachedDeltaForWarning = 0.01;
1970 double delta =
1971 std::abs(m_officialPlaybackPosition - currentPlaybackPosition());
1972 if (delta > minCachedDeltaForWarning) {
1973 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1974 << ") - WARNING, cached time is " << delta
1975 << "seconds off of media time when paused/waiting";
1976 }
1977 #endif
1978
1979 return m_officialPlaybackPosition;
1980 }
1981
1982 void HTMLMediaElement::setOfficialPlaybackPosition(double position) const {
1983 #if LOG_OFFICIAL_TIME_STATUS
1984 BLINK_MEDIA_LOG << "setOfficialPlaybackPosition(" << (void*)this
1985 << ") was:" << m_officialPlaybackPosition
1986 << " now:" << position;
1987 #endif
1988
1989 m_officialPlaybackPosition = position;
1990
1991 // Once set, official playback position should hold steady until the next
1992 // stable state. We approximate this by using a microtask to mark the
1993 // need for an update after the current (micro)task has completed. When
1994 // needed, the update is applied in the next call to
1995 // officialPlaybackPosition().
1996 m_officialPlaybackPositionNeedsUpdate = false;
1997 Microtask::enqueueMicrotask(
1998 WTF::bind(&HTMLMediaElement::requireOfficialPlaybackPositionUpdate,
1999 wrapWeakPersistent(this)));
2000 }
2001
2002 void HTMLMediaElement::requireOfficialPlaybackPositionUpdate() const {
2003 m_officialPlaybackPositionNeedsUpdate = true;
2004 }
2005
1918 double HTMLMediaElement::currentTime() const { 2006 double HTMLMediaElement::currentTime() const {
1919 if (m_defaultPlaybackStartPosition) 2007 if (m_defaultPlaybackStartPosition)
1920 return m_defaultPlaybackStartPosition; 2008 return m_defaultPlaybackStartPosition;
1921 2009
1922 if (m_readyState == kHaveNothing)
1923 return 0;
1924
1925 if (m_seeking) { 2010 if (m_seeking) {
1926 BLINK_MEDIA_LOG << "currentTime(" << (void*)this 2011 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1927 << ") - seeking, returning " << m_lastSeekTime; 2012 << ") - seeking, returning " << m_lastSeekTime;
1928 return m_lastSeekTime; 2013 return m_lastSeekTime;
1929 } 2014 }
1930 2015
1931 if (!std::isnan(m_cachedTime) && m_paused) { 2016 return officialPlaybackPosition();
1932 #if LOG_CACHED_TIME_WARNINGS
1933 static const double minCachedDeltaForWarning = 0.01;
1934 double delta = m_cachedTime - webMediaPlayer()->currentTime();
1935 if (delta > minCachedDeltaForWarning)
1936 BLINK_MEDIA_LOG << "currentTime(" << (void*)this
1937 << ") - WARNING, cached time is " << delta
1938 << "seconds off of media time when paused";
1939 #endif
1940 return m_cachedTime;
1941 }
1942
1943 refreshCachedTime();
1944
1945 return m_cachedTime;
1946 } 2017 }
1947 2018
1948 void HTMLMediaElement::setCurrentTime(double time) { 2019 void HTMLMediaElement::setCurrentTime(double time) {
1949 // If the media element's readyState is kHaveNothing, then set the default 2020 // If the media element's readyState is kHaveNothing, then set the default
1950 // playback start position to that time. 2021 // playback start position to that time.
1951 if (m_readyState == kHaveNothing) { 2022 if (m_readyState == kHaveNothing) {
1952 m_defaultPlaybackStartPosition = time; 2023 m_defaultPlaybackStartPosition = time;
1953 return; 2024 return;
1954 } 2025 }
1955 2026
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 2068
1998 double HTMLMediaElement::playbackRate() const { 2069 double HTMLMediaElement::playbackRate() const {
1999 return m_playbackRate; 2070 return m_playbackRate;
2000 } 2071 }
2001 2072
2002 void HTMLMediaElement::setPlaybackRate(double rate) { 2073 void HTMLMediaElement::setPlaybackRate(double rate) {
2003 BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")"; 2074 BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")";
2004 2075
2005 if (m_playbackRate != rate) { 2076 if (m_playbackRate != rate) {
2006 m_playbackRate = rate; 2077 m_playbackRate = rate;
2007 invalidateCachedTime();
2008 scheduleEvent(EventTypeNames::ratechange); 2078 scheduleEvent(EventTypeNames::ratechange);
2009 } 2079 }
2010 2080
2011 updatePlaybackRate(); 2081 updatePlaybackRate();
2012 } 2082 }
2013 2083
2014 HTMLMediaElement::DirectionOfPlayback HTMLMediaElement::getDirectionOfPlayback() 2084 HTMLMediaElement::DirectionOfPlayback HTMLMediaElement::getDirectionOfPlayback()
2015 const { 2085 const {
2016 return m_playbackRate >= 0 ? Forward : Backward; 2086 return m_playbackRate >= 0 ? Forward : Backward;
2017 } 2087 }
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
2204 invokeResourceSelectionAlgorithm(); 2274 invokeResourceSelectionAlgorithm();
2205 2275
2206 // Generally "ended" and "looping" are exclusive. Here, the loop attribute 2276 // Generally "ended" and "looping" are exclusive. Here, the loop attribute
2207 // is ignored to seek back to start in case loop was set after playback 2277 // is ignored to seek back to start in case loop was set after playback
2208 // ended. See http://crbug.com/364442 2278 // ended. See http://crbug.com/364442
2209 if (endedPlayback(LoopCondition::Ignored)) 2279 if (endedPlayback(LoopCondition::Ignored))
2210 seek(0); 2280 seek(0);
2211 2281
2212 if (m_paused) { 2282 if (m_paused) {
2213 m_paused = false; 2283 m_paused = false;
2214 invalidateCachedTime();
2215 scheduleEvent(EventTypeNames::play); 2284 scheduleEvent(EventTypeNames::play);
2216 2285
2217 if (m_readyState <= kHaveCurrentData) 2286 if (m_readyState <= kHaveCurrentData)
2218 scheduleEvent(EventTypeNames::waiting); 2287 scheduleEvent(EventTypeNames::waiting);
2219 else if (m_readyState >= kHaveFutureData) 2288 else if (m_readyState >= kHaveFutureData)
2220 scheduleNotifyPlaying(); 2289 scheduleNotifyPlaying();
2221 } else if (m_readyState >= kHaveFutureData) { 2290 } else if (m_readyState >= kHaveFutureData) {
2222 scheduleResolvePlayPromises(); 2291 scheduleResolvePlayPromises();
2223 } 2292 }
2224 2293
(...skipping 22 matching lines...) Expand all
2247 invokeResourceSelectionAlgorithm(); 2316 invokeResourceSelectionAlgorithm();
2248 2317
2249 m_autoplayHelper->pauseMethodCalled(); 2318 m_autoplayHelper->pauseMethodCalled();
2250 2319
2251 m_autoplaying = false; 2320 m_autoplaying = false;
2252 2321
2253 if (!m_paused) { 2322 if (!m_paused) {
2254 m_paused = true; 2323 m_paused = true;
2255 scheduleTimeupdateEvent(false); 2324 scheduleTimeupdateEvent(false);
2256 scheduleEvent(EventTypeNames::pause); 2325 scheduleEvent(EventTypeNames::pause);
2326
2327 // Force an update to official playback position. Automatic updates from
2328 // currentPlaybackPosition() will be blocked while m_paused = true. This
2329 // blocking is desired while paused, but its good to update it one final
2330 // time to accurately reflect movie time at the moment we paused.
2331 setOfficialPlaybackPosition(currentPlaybackPosition());
2332
2257 scheduleRejectPlayPromises(AbortError); 2333 scheduleRejectPlayPromises(AbortError);
2258 } 2334 }
2259 2335
2260 updatePlayState(); 2336 updatePlayState();
2261 } 2337 }
2262 2338
2263 void HTMLMediaElement::requestRemotePlayback() { 2339 void HTMLMediaElement::requestRemotePlayback() {
2264 if (webMediaPlayer()) 2340 if (webMediaPlayer())
2265 webMediaPlayer()->requestRemotePlayback(); 2341 webMediaPlayer()->requestRemotePlayback();
2266 } 2342 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 if (!playbackRate()) 2507 if (!playbackRate())
2432 return; 2508 return;
2433 2509
2434 if (!m_paused && mediaControls()) 2510 if (!m_paused && mediaControls())
2435 mediaControls()->playbackProgressed(); 2511 mediaControls()->playbackProgressed();
2436 2512
2437 cueTimeline().updateActiveCues(currentTime()); 2513 cueTimeline().updateActiveCues(currentTime());
2438 } 2514 }
2439 2515
2440 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) { 2516 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) {
2517 // Per spec, consult current playback position to check for changing time.
2518 double mediaTime = currentPlaybackPosition();
2441 double now = WTF::currentTime(); 2519 double now = WTF::currentTime();
2442 double movieTime = currentTime();
2443 2520
2444 bool haveNotRecentlyFiredTimeupdate = 2521 bool haveNotRecentlyFiredTimeupdate =
2445 (now - m_lastTimeUpdateEventWallTime) >= maxTimeupdateEventFrequency; 2522 (now - m_lastTimeUpdateEventWallTime) >= maxTimeupdateEventFrequency;
2446 bool movieTimeHasProgressed = movieTime != m_lastTimeUpdateEventMovieTime; 2523 bool mediaTimeHasProgressed = mediaTime != m_lastTimeUpdateEventMediaTime;
2447 2524
2448 // Non-periodic timeupdate events must always fire as mandated by the spec, 2525 // Non-periodic timeupdate events must always fire as mandated by the spec,
2449 // otherwise we shouldn't fire duplicate periodic timeupdate events when the 2526 // otherwise we shouldn't fire duplicate periodic timeupdate events when the
2450 // movie time hasn't changed. 2527 // movie time hasn't changed.
2451 if (!periodicEvent || 2528 if (!periodicEvent ||
2452 (haveNotRecentlyFiredTimeupdate && movieTimeHasProgressed)) { 2529 (haveNotRecentlyFiredTimeupdate && mediaTimeHasProgressed)) {
2453 scheduleEvent(EventTypeNames::timeupdate); 2530 scheduleEvent(EventTypeNames::timeupdate);
2454 m_lastTimeUpdateEventWallTime = now; 2531 m_lastTimeUpdateEventWallTime = now;
2455 m_lastTimeUpdateEventMovieTime = movieTime; 2532 m_lastTimeUpdateEventMediaTime = mediaTime;
2456 } 2533 }
2457 } 2534 }
2458 2535
2459 void HTMLMediaElement::togglePlayState() { 2536 void HTMLMediaElement::togglePlayState() {
2460 if (paused()) 2537 if (paused())
2461 play(); 2538 play();
2462 else 2539 else
2463 pause(); 2540 pause();
2464 } 2541 }
2465 2542
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2977 BLINK_MEDIA_LOG << "sourceWasRemoved(" << (void*)this 3054 BLINK_MEDIA_LOG << "sourceWasRemoved(" << (void*)this
2978 << ") - m_currentSourceNode set to 0"; 3055 << ") - m_currentSourceNode set to 0";
2979 } 3056 }
2980 } 3057 }
2981 3058
2982 void HTMLMediaElement::timeChanged() { 3059 void HTMLMediaElement::timeChanged() {
2983 BLINK_MEDIA_LOG << "timeChanged(" << (void*)this << ")"; 3060 BLINK_MEDIA_LOG << "timeChanged(" << (void*)this << ")";
2984 3061
2985 cueTimeline().updateActiveCues(currentTime()); 3062 cueTimeline().updateActiveCues(currentTime());
2986 3063
2987 invalidateCachedTime();
2988
2989 // 4.8.10.9 steps 12-14. Needed if no ReadyState change is associated with the 3064 // 4.8.10.9 steps 12-14. Needed if no ReadyState change is associated with the
2990 // seek. 3065 // seek.
2991 if (m_seeking && m_readyState >= kHaveCurrentData && 3066 if (m_seeking && m_readyState >= kHaveCurrentData &&
2992 !webMediaPlayer()->seeking()) 3067 !webMediaPlayer()->seeking())
2993 finishSeek(); 3068 finishSeek();
2994 3069
2995 // Always call scheduleTimeupdateEvent when the media engine reports a time 3070 // Always call scheduleTimeupdateEvent when the media engine reports a time
2996 // discontinuity, it will only queue a 'timeupdate' event if we haven't 3071 // discontinuity, it will only queue a 'timeupdate' event if we haven't
2997 // already posted one at the current movie time. 3072 // already posted one at the current movie time.
2998 scheduleTimeupdateEvent(false); 3073 scheduleTimeupdateEvent(false);
2999 3074
3000 double now = currentTime(); 3075 double now = currentPlaybackPosition();
3001 double dur = duration(); 3076 double dur = duration();
3002 3077
3003 // When the current playback position reaches the end of the media resource 3078 // When the current playback position reaches the end of the media resource
3004 // when the direction of playback is forwards, then the user agent must follow 3079 // when the direction of playback is forwards, then the user agent must follow
3005 // these steps: 3080 // these steps:
3006 if (!std::isnan(dur) && dur && now >= dur && 3081 if (!std::isnan(dur) && dur && now >= dur &&
3007 getDirectionOfPlayback() == Forward) { 3082 getDirectionOfPlayback() == Forward) {
3008 // If the media element has a loop attribute specified 3083 // If the media element has a loop attribute specified
3009 if (loop()) { 3084 if (loop()) {
3010 // then seek to the earliest possible position of the media resource and 3085 // then seek to the earliest possible position of the media resource and
3011 // abort these steps. 3086 // abort these steps.
3012 seek(0); 3087 seek(earliestPossiblePosition());
3013 } else { 3088 } else {
3014 // If the media element has still ended playback, and the direction of 3089 // If the media element has still ended playback, and the direction of
3015 // playback is still forwards, and paused is false, 3090 // playback is still forwards, and paused is false,
3016 if (!m_paused) { 3091 if (!m_paused) {
3017 // changes paused to true and fires a simple event named pause at the 3092 // changes paused to true and fires a simple event named pause at the
3018 // media element. 3093 // media element.
3019 m_paused = true; 3094 m_paused = true;
3020 scheduleEvent(EventTypeNames::pause); 3095 scheduleEvent(EventTypeNames::pause);
3021 scheduleRejectPlayPromises(AbortError); 3096 scheduleRejectPlayPromises(AbortError);
3022 } 3097 }
3023 // Queue a task to fire a simple event named ended at the media element. 3098 // Queue a task to fire a simple event named ended at the media element.
3024 scheduleEvent(EventTypeNames::ended); 3099 scheduleEvent(EventTypeNames::ended);
3025 } 3100 }
3026 } 3101 }
3027 updatePlayState(); 3102 updatePlayState();
3028 } 3103 }
3029 3104
3030 void HTMLMediaElement::durationChanged() { 3105 void HTMLMediaElement::durationChanged() {
3031 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ")"; 3106 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ")";
3032 // FIXME: Change WebMediaPlayer to convey the currentTime 3107 // If the duration is changed such that the *current playback position* ends
3033 // when the duration change occured. The current WebMediaPlayer 3108 // up being greater than the time of the end of the media resource, then the
3034 // implementations always clamp currentTime() to duration() 3109 // user agent must also seek to the time of the end of the media resource.
3035 // so the requestSeek condition here is always false. 3110 durationChanged(duration(), currentPlaybackPosition() > duration());
3036 durationChanged(duration(), currentTime() > duration());
3037 } 3111 }
3038 3112
3039 void HTMLMediaElement::durationChanged(double duration, bool requestSeek) { 3113 void HTMLMediaElement::durationChanged(double duration, bool requestSeek) {
3040 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ", " << duration 3114 BLINK_MEDIA_LOG << "durationChanged(" << (void*)this << ", " << duration
3041 << ", " << boolString(requestSeek) << ")"; 3115 << ", " << boolString(requestSeek) << ")";
3042 3116
3043 // Abort if duration unchanged. 3117 // Abort if duration unchanged.
3044 if (m_duration == duration) 3118 if (m_duration == duration)
3045 return; 3119 return;
3046 3120
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
3189 // 4.8.10.8 Playing the media resource 3263 // 4.8.10.8 Playing the media resource
3190 3264
3191 // A media element is said to have ended playback when the element's 3265 // A media element is said to have ended playback when the element's
3192 // readyState attribute is HAVE_METADATA or greater, 3266 // readyState attribute is HAVE_METADATA or greater,
3193 if (m_readyState < kHaveMetadata) 3267 if (m_readyState < kHaveMetadata)
3194 return false; 3268 return false;
3195 3269
3196 // and the current playback position is the end of the media resource and the 3270 // and the current playback position is the end of the media resource and the
3197 // direction of playback is forwards, Either the media element does not have a 3271 // direction of playback is forwards, Either the media element does not have a
3198 // loop attribute specified, 3272 // loop attribute specified,
3199 double now = currentTime(); 3273 double now = currentPlaybackPosition();
3200 if (getDirectionOfPlayback() == Forward) 3274 if (getDirectionOfPlayback() == Forward)
3201 return dur > 0 && now >= dur && 3275 return dur > 0 && now >= dur &&
3202 (loopCondition == LoopCondition::Ignored || !loop()); 3276 (loopCondition == LoopCondition::Ignored || !loop());
3203 3277
3204 // or the current playback position is the earliest possible position and the 3278 // or the current playback position is the earliest possible position and the
3205 // direction of playback is backwards 3279 // direction of playback is backwards
3206 DCHECK_EQ(getDirectionOfPlayback(), Backward); 3280 DCHECK_EQ(getDirectionOfPlayback(), Backward);
3207 return now <= 0; 3281 return now <= earliestPossiblePosition();
3208 } 3282 }
3209 3283
3210 bool HTMLMediaElement::stoppedDueToErrors() const { 3284 bool HTMLMediaElement::stoppedDueToErrors() const {
3211 if (m_readyState >= kHaveMetadata && m_error) { 3285 if (m_readyState >= kHaveMetadata && m_error) {
3212 TimeRanges* seekableRanges = seekable(); 3286 TimeRanges* seekableRanges = seekable();
3213 if (!seekableRanges->contain(currentTime())) 3287 if (!seekableRanges->contain(currentTime()))
3214 return true; 3288 return true;
3215 } 3289 }
3216 3290
3217 return false; 3291 return false;
3218 } 3292 }
3219 3293
3220 void HTMLMediaElement::updatePlayState() { 3294 void HTMLMediaElement::updatePlayState() {
3221 bool isPlaying = webMediaPlayer() && !webMediaPlayer()->paused(); 3295 bool isPlaying = webMediaPlayer() && !webMediaPlayer()->paused();
3222 bool shouldBePlaying = potentiallyPlaying(); 3296 bool shouldBePlaying = potentiallyPlaying();
3223 3297
3224 BLINK_MEDIA_LOG << "updatePlayState(" << (void*)this 3298 BLINK_MEDIA_LOG << "updatePlayState(" << (void*)this
3225 << ") - shouldBePlaying = " << boolString(shouldBePlaying) 3299 << ") - shouldBePlaying = " << boolString(shouldBePlaying)
3226 << ", isPlaying = " << boolString(isPlaying); 3300 << ", isPlaying = " << boolString(isPlaying);
3227 3301
3228 if (shouldBePlaying) { 3302 if (shouldBePlaying) {
3229 setDisplayMode(Video); 3303 setDisplayMode(Video);
3230 invalidateCachedTime();
3231 3304
3232 if (!isPlaying) { 3305 if (!isPlaying) {
3233 // Set rate, muted before calling play in case they were set before the 3306 // Set rate, muted before calling play in case they were set before the
3234 // media engine was setup. The media engine should just stash the rate 3307 // media engine was setup. The media engine should just stash the rate
3235 // and muted values since it isn't already playing. 3308 // and muted values since it isn't already playing.
3236 webMediaPlayer()->setRate(playbackRate()); 3309 webMediaPlayer()->setRate(playbackRate());
3237 updateVolume(); 3310 updateVolume();
3238 webMediaPlayer()->play(); 3311 webMediaPlayer()->play();
3239 m_autoplayHelper->playbackStarted(); 3312 m_autoplayHelper->playbackStarted();
3240 } 3313 }
3241 3314
3242 if (mediaControls()) 3315 if (mediaControls())
3243 mediaControls()->playbackStarted(); 3316 mediaControls()->playbackStarted();
3244 startPlaybackProgressTimer(); 3317 startPlaybackProgressTimer();
3245 m_playing = true; 3318 m_playing = true;
3246 3319
3247 } else { // Should not be playing right now 3320 } else { // Should not be playing right now
3248 if (isPlaying) { 3321 if (isPlaying) {
3249 webMediaPlayer()->pause(); 3322 webMediaPlayer()->pause();
3250 m_autoplayHelper->playbackStopped(); 3323 m_autoplayHelper->playbackStopped();
3251 } 3324 }
3252 3325
3253 refreshCachedTime();
3254
3255 m_playbackProgressTimer.stop(); 3326 m_playbackProgressTimer.stop();
3256 m_playing = false; 3327 m_playing = false;
3257 double time = currentTime(); 3328 double time = currentTime();
3258 if (time > m_lastSeekTime) 3329 if (time > m_lastSeekTime)
3259 addPlayedRange(m_lastSeekTime, time); 3330 addPlayedRange(m_lastSeekTime, time);
3260 3331
3261 if (mediaControls()) 3332 if (mediaControls())
3262 mediaControls()->playbackStopped(); 3333 mediaControls()->playbackStopped();
3263 } 3334 }
3264 3335
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 cancelPendingEventsAndCallbacks(); 3386 cancelPendingEventsAndCallbacks();
3316 m_asyncEventQueue->close(); 3387 m_asyncEventQueue->close();
3317 3388
3318 // Clear everything in the Media Element 3389 // Clear everything in the Media Element
3319 clearMediaPlayer(); 3390 clearMediaPlayer();
3320 m_readyState = kHaveNothing; 3391 m_readyState = kHaveNothing;
3321 m_readyStateMaximum = kHaveNothing; 3392 m_readyStateMaximum = kHaveNothing;
3322 setNetworkState(kNetworkEmpty); 3393 setNetworkState(kNetworkEmpty);
3323 setShouldDelayLoadEvent(false); 3394 setShouldDelayLoadEvent(false);
3324 m_currentSourceNode = nullptr; 3395 m_currentSourceNode = nullptr;
3325 invalidateCachedTime(); 3396 m_officialPlaybackPosition = 0;
3397 m_officialPlaybackPositionNeedsUpdate = true;
3326 cueTimeline().updateActiveCues(0); 3398 cueTimeline().updateActiveCues(0);
3327 m_playing = false; 3399 m_playing = false;
3328 m_paused = true; 3400 m_paused = true;
3329 m_seeking = false; 3401 m_seeking = false;
3330 3402
3331 if (layoutObject()) 3403 if (layoutObject())
3332 layoutObject()->updateFromElement(); 3404 layoutObject()->updateFromElement();
3333 3405
3334 stopPeriodicTimers(); 3406 stopPeriodicTimers();
3335 3407
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
3962 ("Media.Controls.Show.Audio", MediaControlsShowMax)); 4034 ("Media.Controls.Show.Audio", MediaControlsShowMax));
3963 return histogram; 4035 return histogram;
3964 } 4036 }
3965 4037
3966 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { 4038 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) {
3967 if (!isVisible) 4039 if (!isVisible)
3968 return; 4040 return;
3969 4041
3970 if (shouldAutoplay()) { 4042 if (shouldAutoplay()) {
3971 m_paused = false; 4043 m_paused = false;
3972 invalidateCachedTime();
3973 scheduleEvent(EventTypeNames::play); 4044 scheduleEvent(EventTypeNames::play);
3974 scheduleNotifyPlaying(); 4045 scheduleNotifyPlaying();
3975 m_autoplaying = false; 4046 m_autoplaying = false;
3976 4047
3977 updatePlayState(); 4048 updatePlayState();
3978 } 4049 }
3979 4050
3980 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay() 4051 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay()
3981 // is never called. The leak comes from either ElementVisibilityObserver or 4052 // is never called. The leak comes from either ElementVisibilityObserver or
3982 // IntersectionObserver. Should keep an eye on it. See 4053 // IntersectionObserver. Should keep an eye on it. See
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
4087 4158
4088 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() 4159 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect()
4089 const { 4160 const {
4090 IntRect result; 4161 IntRect result;
4091 if (LayoutObject* object = m_element->layoutObject()) 4162 if (LayoutObject* object = m_element->layoutObject())
4092 result = object->absoluteBoundingBoxRect(); 4163 result = object->absoluteBoundingBoxRect();
4093 return result; 4164 return result;
4094 } 4165 }
4095 4166
4096 } // namespace blink 4167 } // 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