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

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

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