Index: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp |
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp |
index 7a3c5bb811ac9c53744959f8ea10062c0685cee2..2918ec008e902f45f3fcdc98ddf1d218ba6c54e0 100644 |
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp |
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp |
@@ -459,8 +459,7 @@ void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) |
// A proper fix would provide a mechanism to allow this object to refresh |
// the MediaPlayer's LocalFrame and FrameLoader references on |
// document changes so that playback can be resumed properly. |
- clearMediaPlayer(LoadMediaResource); |
- scheduleDelayedAction(LoadMediaResource); |
+ invokeLoadAlgorithm(); |
ddorwin
2016/02/02 20:24:22
I don't know if this is related, but you are no lo
|
// Decrement the load event delay count on oldDocument now that m_webMediaPlayer has been destroyed |
// and there is no risk of dispatching a load event from within the destructor. |
@@ -489,8 +488,7 @@ void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicStr |
if (name == srcAttr) { |
// Trigger a reload, as long as the 'src' attribute is present. |
if (!value.isNull()) { |
- clearMediaPlayer(LoadMediaResource); |
- scheduleDelayedAction(LoadMediaResource); |
+ invokeLoadAlgorithm(); |
} |
} else if (name == controlsAttr) { |
configureMediaControls(); |
@@ -508,7 +506,7 @@ void HTMLMediaElement::finishParsingChildren() |
HTMLElement::finishParsingChildren(); |
if (Traversal<HTMLTrackElement>::firstChild(*this)) |
- scheduleDelayedAction(LoadTextTrackResource); |
+ scheduleTextTrackResourceLoad(); |
} |
bool HTMLMediaElement::layoutObjectIsNeeded(const ComputedStyle& style) |
@@ -527,8 +525,9 @@ Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode* |
HTMLElement::insertedInto(insertionPoint); |
if (insertionPoint->inDocument()) { |
- if (!getAttribute(srcAttr).isEmpty() && m_networkState == NETWORK_EMPTY) |
- scheduleDelayedAction(LoadMediaResource); |
+ if (!getAttribute(srcAttr).isEmpty() && m_networkState == NETWORK_EMPTY) { |
+ invokeResourceSelectionAlgorithm(); |
jrummell
2016/02/02 21:39:07
Is this correct? previous calls to scheduleDelayed
|
+ } |
} |
return InsertionShouldCallDidNotifySubtreeInsertions; |
@@ -565,17 +564,11 @@ void HTMLMediaElement::didRecalcStyle(StyleRecalcChange) |
layoutObject()->updateFromElement(); |
} |
-void HTMLMediaElement::scheduleDelayedAction(DelayedActionType actionType) |
+void HTMLMediaElement::scheduleTextTrackResourceLoad() |
{ |
- WTF_LOG(Media, "HTMLMediaElement::scheduleDelayedAction(%p)", this); |
- |
- if ((actionType & LoadMediaResource) && !(m_pendingActionFlags & LoadMediaResource)) { |
- prepareForLoad(); |
- m_pendingActionFlags |= LoadMediaResource; |
- } |
+ WTF_LOG(Media, "HTMLMediaElement::scheduleTextTrackResourceLoad(%p)", this); |
- if (actionType & LoadTextTrackResource) |
- m_pendingActionFlags |= LoadTextTrackResource; |
+ m_pendingActionFlags |= LoadTextTrackResource; |
if (!m_loadTimer.isActive()) |
m_loadTimer.startOneShot(0, BLINK_FROM_HERE); |
@@ -701,22 +694,20 @@ void HTMLMediaElement::load() |
prepareToPlay(); |
} |
+void HTMLMediaElement::invokeLoadAlgorithm() |
+{ |
+ WTF_LOG(Media, "HTMLMediaElement::invokeLoadAlgorithm(%p)", this); |
+ |
+ prepareForLoad(); |
jrummell
2016/02/02 21:39:08
The previous scheduleDelayedAction() only called p
|
+ scheduleNextSourceChild(); |
+} |
+ |
void HTMLMediaElement::prepareForLoad() |
{ |
WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); |
- // Perform the cleanup required for the resource load algorithm to run. |
- stopPeriodicTimers(); |
- m_loadTimer.stop(); |
- cancelDeferredLoad(); |
- // FIXME: Figure out appropriate place to reset LoadTextTrackResource if necessary and set m_pendingActionFlags to 0 here. |
- m_pendingActionFlags &= ~LoadMediaResource; |
- m_sentEndEvent = false; |
- m_sentStalledEvent = false; |
- m_haveFiredLoadedData = false; |
- m_completelyLoaded = false; |
- m_havePreparedToPlay = false; |
- m_displayMode = Unknown; |
+ NetworkState networkState = m_networkState; |
+ resetMediaElement(LoadMediaResource); |
// 1 - Abort any already-running instance of the resource selection algorithm for this element. |
m_loadState = WaitingForSource; |
@@ -728,13 +719,11 @@ void HTMLMediaElement::prepareForLoad() |
// 3 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, queue |
// a task to fire a simple event named abort at the media element. |
- if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) |
+ if (networkState == NETWORK_LOADING || networkState == NETWORK_IDLE) |
scheduleEvent(EventTypeNames::abort); |
- resetMediaPlayerAndMediaSource(); |
- |
// 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps |
- if (m_networkState != NETWORK_EMPTY) { |
+ if (networkState != NETWORK_EMPTY) { |
// 4.1 - Queue a task to fire a simple event named emptied at the media element. |
scheduleEvent(EventTypeNames::emptied); |
@@ -777,14 +766,20 @@ void HTMLMediaElement::prepareForLoad() |
m_autoplaying = true; |
// 7 - Invoke the media element's resource selection algorithm. |
+ invokeResourceSelectionAlgorithm(); |
// 8 - Note: Playback of any previously playing media resource for this element stops. |
+} |
+void HTMLMediaElement::invokeResourceSelectionAlgorithm() |
+{ |
+ WTF_LOG(Media, "HTMLMediaElement::invokeResourceSelectionAlgorithm(%p)", this); |
// The resource selection algorithm |
// 1 - Set the networkState to NETWORK_NO_SOURCE |
setNetworkState(NETWORK_NO_SOURCE); |
- // 2 - Asynchronously await a stable state. |
+ // 2 - Set the element's show poster flag to true |
+ // TODO(srirama.m): Introduce show poster flag and update it as per spec |
m_playedTimeRanges = TimeRanges::create(); |
@@ -793,12 +788,13 @@ void HTMLMediaElement::prepareForLoad() |
m_lastSeekTime = 0; |
m_duration = std::numeric_limits<double>::quiet_NaN(); |
- // The spec doesn't say to block the load event until we actually run the asynchronous section |
- // algorithm, but do it now because we won't start that until after the timer fires and the |
- // event may have already fired by then. |
+ // 3 - Set the media element's delaying-the-load-event flag to true (this delays the load event) |
setShouldDelayLoadEvent(true); |
if (mediaControls()) |
mediaControls()->reset(); |
+ |
+ // 4 - Await a stable state, allowing the task that invoked this algorithm to continue |
+ // TODO(srirama.m): Schedule an async continuation of this algorithm as per the spec |
} |
void HTMLMediaElement::loadInternal() |
@@ -1965,8 +1961,10 @@ void HTMLMediaElement::playInternal() |
webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy::Normal); |
// 4.8.10.9. Playing the media resource |
- if (m_networkState == NETWORK_EMPTY) |
- scheduleDelayedAction(LoadMediaResource); |
+ if (m_networkState == NETWORK_EMPTY) { |
+ invokeResourceSelectionAlgorithm(); |
+ scheduleNextSourceChild(); |
+ } |
// Generally "ended" and "looping" are exclusive. Here, the loop attribute |
// is ignored to seek back to start in case loop was set after playback |
@@ -2025,8 +2023,10 @@ void HTMLMediaElement::pauseInternal() |
{ |
WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); |
- if (m_networkState == NETWORK_EMPTY) |
- scheduleDelayedAction(LoadMediaResource); |
+ if (m_networkState == NETWORK_EMPTY) { |
+ invokeResourceSelectionAlgorithm(); |
+ scheduleNextSourceChild(); |
+ } |
m_autoplayHelper.pauseMethodCalled(); |
@@ -2339,7 +2339,7 @@ void HTMLMediaElement::addTextTrack(WebInbandTextTrack* webTrack) |
// 7. Set the new text track's mode to the mode consistent with the user's preferences and the requirements of |
// the relevant specification for the data. |
// - This will happen in honorUserPreferencesForAutomaticTextTrackSelection() |
- scheduleDelayedAction(LoadTextTrackResource); |
+ scheduleTextTrackResourceLoad(); |
// 8. Add the new text track to the media element's list of text tracks. |
// 9. Fire an event with the name addtrack, that does not bubble and is not cancelable, and that uses the TrackEvent |
@@ -2459,7 +2459,7 @@ void HTMLMediaElement::didAddTrackElement(HTMLTrackElement* trackElement) |
// Do not schedule the track loading until parsing finishes so we don't start before all tracks |
// in the markup have been added. |
if (isFinishedParsingChildren()) |
- scheduleDelayedAction(LoadTextTrackResource); |
+ scheduleTextTrackResourceLoad(); |
} |
void HTMLMediaElement::didRemoveTrackElement(HTMLTrackElement* trackElement) |
@@ -2636,7 +2636,8 @@ void HTMLMediaElement::sourceWasAdded(HTMLSourceElement* source) |
// attribute and whose networkState has the value NETWORK_EMPTY, the user agent must invoke |
// the media element's resource selection algorithm. |
if (networkState() == HTMLMediaElement::NETWORK_EMPTY) { |
- scheduleDelayedAction(LoadMediaResource); |
+ invokeResourceSelectionAlgorithm(); |
+ scheduleNextSourceChild(); |
m_nextChildNodeToConsider = source; |
return; |
} |
@@ -2986,7 +2987,7 @@ void HTMLMediaElement::clearMediaPlayerAndAudioSourceProviderClientWithoutLockin |
} |
} |
-void HTMLMediaElement::clearMediaPlayer(int flags) |
+void HTMLMediaElement::resetMediaElement(int flags) |
{ |
forgetResourceSpecificTracks(); |
@@ -2999,6 +3000,11 @@ void HTMLMediaElement::clearMediaPlayer(int flags) |
clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); |
} |
+#if ENABLE(WEB_AUDIO) |
+ if (m_audioSourceNode) |
+ audioSourceProvider().setClient(m_audioSourceNode); |
+#endif |
+ |
stopPeriodicTimers(); |
m_loadTimer.stop(); |
@@ -3008,6 +3014,26 @@ void HTMLMediaElement::clearMediaPlayer(int flags) |
// We can't cast if we don't have a media player. |
m_remoteRoutesAvailable = false; |
m_playingRemotely = false; |
+ |
+ // FIXME: Figure out appropriate place to reset LoadTextTrackResource if necessary and set m_pendingActionFlags to 0 here. |
+ m_sentEndEvent = false; |
+ m_sentStalledEvent = false; |
+ m_haveFiredLoadedData = false; |
+ m_completelyLoaded = false; |
+ m_havePreparedToPlay = false; |
+ m_displayMode = Unknown; |
+ |
+ m_readyState = HAVE_NOTHING; |
+ m_readyStateMaximum = HAVE_NOTHING; |
+ setNetworkState(NETWORK_EMPTY); |
+ setShouldDelayLoadEvent(false); |
+ m_currentSourceNode = nullptr; |
+ invalidateCachedTime(); |
+ cueTimeline().updateActiveCues(0); |
+ m_playing = false; |
+ m_paused = true; |
+ m_seeking = false; |
+ |
if (mediaControls()) |
mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); |
@@ -3025,24 +3051,12 @@ void HTMLMediaElement::stop() |
cancelPendingEventsAndCallbacks(); |
m_asyncEventQueue->close(); |
- // Stop the playback without generating events |
- clearMediaPlayer(-1); |
- m_readyState = HAVE_NOTHING; |
- m_readyStateMaximum = HAVE_NOTHING; |
- setNetworkState(NETWORK_EMPTY); |
- setShouldDelayLoadEvent(false); |
- m_currentSourceNode = nullptr; |
- invalidateCachedTime(); |
- cueTimeline().updateActiveCues(0); |
- m_playing = false; |
- m_paused = true; |
- m_seeking = false; |
+ // Clear everything in the Media Element |
+ resetMediaElement(-1); |
if (layoutObject()) |
layoutObject()->updateFromElement(); |
- stopPeriodicTimers(); |
- |
// Ensure that hasPendingActivity() is not preventing garbage collection, since otherwise this |
// media element will simply leak. |
ASSERT(!hasPendingActivity()); |
@@ -3391,7 +3405,7 @@ void* HTMLMediaElement::preDispatchEventHandler(Event* event) |
return nullptr; |
} |
-// TODO(srirama.m): Refactor this and clearMediaPlayer to the extent possible. |
+// TODO(srirama.m): Merge it to resetMediaElement if possible and remove it. |
void HTMLMediaElement::resetMediaPlayerAndMediaSource() |
{ |
closeMediaSource(); |