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

Unified Diff: Source/core/html/HTMLMediaElement.cpp

Issue 913133003: Move text track active list management to CueTimeline (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rename to CueTimeline. Created 5 years, 10 months 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/html/HTMLMediaElement.cpp
diff --git a/Source/core/html/HTMLMediaElement.cpp b/Source/core/html/HTMLMediaElement.cpp
index d950813509f57be4ced709d0b6c95b819abd7b1e..ba07c0e0234aa84ca8e8590202484f47ab69df1b 100644
--- a/Source/core/html/HTMLMediaElement.cpp
+++ b/Source/core/html/HTMLMediaElement.cpp
@@ -53,8 +53,8 @@
#include "core/html/track/AudioTrack.h"
#include "core/html/track/AudioTrackList.h"
#include "core/html/track/AutomaticTrackSelection.h"
+#include "core/html/track/CueTimeline.h"
#include "core/html/track/InbandTextTrack.h"
-#include "core/html/track/TextTrackCueList.h"
#include "core/html/track/TextTrackList.h"
#include "core/html/track/VideoTrack.h"
#include "core/html/track/VideoTrackList.h"
@@ -75,7 +75,6 @@
#include "public/platform/WebInbandTextTrack.h"
#include "wtf/CurrentTime.h"
#include "wtf/MathExtras.h"
-#include "wtf/NonCopyingSort.h"
#include "wtf/text/CString.h"
#include <limits>
@@ -149,24 +148,6 @@ static void removeElementFromDocumentMap(HTMLMediaElement* element, Document* do
map.add(document, set);
}
-class TrackDisplayUpdateScope {
- STACK_ALLOCATED();
-public:
- TrackDisplayUpdateScope(HTMLMediaElement* mediaElement)
- {
- m_mediaElement = mediaElement;
- m_mediaElement->beginIgnoringTrackDisplayUpdateRequests();
- }
- ~TrackDisplayUpdateScope()
- {
- ASSERT(m_mediaElement);
- m_mediaElement->endIgnoringTrackDisplayUpdateRequests();
- }
-
-private:
- RawPtrWillBeMember<HTMLMediaElement> m_mediaElement;
-};
-
class AudioSourceProviderClientLockScope {
STACK_ALLOCATED();
public:
@@ -375,13 +356,11 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
, m_isFinalizing(false)
, m_closeMediaSourceWhenFinalizing(false)
#endif
- , m_lastTextTrackUpdateTime(-1)
, m_initialPlayWithoutUserGestures(false)
, m_autoplayMediaCounted(false)
, m_audioTracks(AudioTrackList::create(*this))
, m_videoTracks(VideoTrackList::create(*this))
, m_textTracks(nullptr)
- , m_ignoreTrackDisplayUpdate(0)
#if ENABLE(WEB_AUDIO)
, m_audioSourceNode(nullptr)
#endif
@@ -818,7 +797,7 @@ void HTMLMediaElement::prepareForLoad()
updateMediaController();
- updateActiveTextTrackCues(0);
+ cueTimeline().updateActiveCues(0);
}
// 5 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
@@ -1140,262 +1119,6 @@ WebMediaPlayer::LoadType HTMLMediaElement::loadType() const
return WebMediaPlayer::LoadTypeURL;
}
-static bool trackIndexCompare(TextTrack* a,
- TextTrack* b)
-{
- return a->trackIndex() - b->trackIndex() < 0;
-}
-
-static bool eventTimeCueCompare(const std::pair<double, TextTrackCue*>& a,
- const std::pair<double, TextTrackCue*>& b)
-{
- // 12 - Sort the tasks in events in ascending time order (tasks with earlier
- // times first).
- if (a.first != b.first)
- return a.first - b.first < 0;
-
- // If the cues belong to different text tracks, it doesn't make sense to
- // compare the two tracks by the relative cue order, so return the relative
- // track order.
- if (a.second->track() != b.second->track())
- return trackIndexCompare(a.second->track(), b.second->track());
-
- // 12 - Further sort tasks in events that have the same time by the
- // relative text track cue order of the text track cues associated
- // with these tasks.
- return a.second->cueIndex() - b.second->cueIndex() < 0;
-}
-
-
-void HTMLMediaElement::updateActiveTextTrackCues(double movieTime)
-{
- // 4.8.10.8 Playing the media resource
-
- // If the current playback position changes while the steps are running,
- // then the user agent must wait for the steps to complete, and then must
- // immediately rerun the steps.
- if (ignoreTrackDisplayUpdateRequests())
- return;
-
- // 1 - Let current cues be a list of cues, initialized to contain all the
- // cues of all the hidden, showing, or showing by default text tracks of the
- // media element (not the disabled ones) whose start times are less than or
- // equal to the current playback position and whose end times are greater
- // than the current playback position.
- CueList currentCues;
-
- // The user agent must synchronously unset [the text track cue active] flag
- // whenever ... the media element's readyState is changed back to HAVE_NOTHING.
- if (m_readyState != HAVE_NOTHING && m_player)
- currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime));
-
- CueList previousCues;
- CueList missedCues;
-
- // 2 - Let other cues be a list of cues, initialized to contain all the cues
- // of hidden, showing, and showing by default text tracks of the media
- // element that are not present in current cues.
- previousCues = m_currentlyActiveCues;
-
- // 3 - Let last time be the current playback position at the time this
- // algorithm was last run for this media element, if this is not the first
- // time it has run.
- double lastTime = m_lastTextTrackUpdateTime;
-
- // 4 - If the current playback position has, since the last time this
- // algorithm was run, only changed through its usual monotonic increase
- // during normal playback, then let missed cues be the list of cues in other
- // cues whose start times are greater than or equal to last time and whose
- // end times are less than or equal to the current playback position.
- // Otherwise, let missed cues be an empty list.
- if (lastTime >= 0 && m_lastSeekTime < movieTime) {
- CueList potentiallySkippedCues =
- m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime));
-
- for (CueInterval cue : potentiallySkippedCues) {
- // Consider cues that may have been missed since the last seek time.
- if (cue.low() > std::max(m_lastSeekTime, lastTime) && cue.high() < movieTime)
- missedCues.append(cue);
- }
- }
-
- m_lastTextTrackUpdateTime = movieTime;
-
- // 5 - If the time was reached through the usual monotonic increase of the
- // current playback position during normal playback, and if the user agent
- // has not fired a timeupdate event at the element in the past 15 to 250ms
- // and is not still running event handlers for such an event, then the user
- // agent must queue a task to fire a simple event named timeupdate at the
- // element. (In the other cases, such as explicit seeks, relevant events get
- // fired as part of the overall process of changing the current playback
- // position.)
- if (!m_seeking && m_lastSeekTime < lastTime)
- scheduleTimeupdateEvent(true);
-
- // Explicitly cache vector sizes, as their content is constant from here.
- size_t currentCuesSize = currentCues.size();
- size_t missedCuesSize = missedCues.size();
- size_t previousCuesSize = previousCues.size();
-
- // 6 - If all of the cues in current cues have their text track cue active
- // flag set, none of the cues in other cues have their text track cue active
- // flag set, and missed cues is empty, then abort these steps.
- bool activeSetChanged = missedCuesSize;
-
- for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i) {
- if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive())
- activeSetChanged = true;
- }
-
- for (CueInterval currentCue : currentCues) {
- currentCue.data()->updateDisplayTree(movieTime);
-
- if (!currentCue.data()->isActive())
- activeSetChanged = true;
- }
-
- if (!activeSetChanged)
- return;
-
- // 7 - If the time was reached through the usual monotonic increase of the
- // current playback position during normal playback, and there are cues in
- // other cues that have their text track cue pause-on-exi flag set and that
- // either have their text track cue active flag set or are also in missed
- // cues, then immediately pause the media element.
- for (size_t i = 0; !m_paused && i < previousCuesSize; ++i) {
- if (previousCues[i].data()->pauseOnExit()
- && previousCues[i].data()->isActive()
- && !currentCues.contains(previousCues[i]))
- pause();
- }
-
- for (size_t i = 0; !m_paused && i < missedCuesSize; ++i) {
- if (missedCues[i].data()->pauseOnExit())
- pause();
- }
-
- // 8 - Let events be a list of tasks, initially empty. Each task in this
- // list will be associated with a text track, a text track cue, and a time,
- // which are used to sort the list before the tasks are queued.
- WillBeHeapVector<std::pair<double, RawPtrWillBeMember<TextTrackCue>>> eventTasks;
-
- // 8 - Let affected tracks be a list of text tracks, initially empty.
- WillBeHeapVector<RawPtrWillBeMember<TextTrack>> affectedTracks;
-
- for (size_t i = 0; i < missedCuesSize; ++i) {
- // 9 - For each text track cue in missed cues, prepare an event named enter
- // for the TextTrackCue object with the text track cue start time.
- eventTasks.append(std::make_pair(missedCues[i].data()->startTime(),
- missedCues[i].data()));
-
- // 10 - For each text track [...] in missed cues, prepare an event
- // named exit for the TextTrackCue object with the with the later of
- // the text track cue end time and the text track cue start time.
-
- // Note: An explicit task is added only if the cue is NOT a zero or
- // negative length cue. Otherwise, the need for an exit event is
- // checked when these tasks are actually queued below. This doesn't
- // affect sorting events before dispatch either, because the exit
- // event has the same time as the enter event.
- if (missedCues[i].data()->startTime() < missedCues[i].data()->endTime())
- eventTasks.append(std::make_pair(missedCues[i].data()->endTime(),
- missedCues[i].data()));
- }
-
- for (size_t i = 0; i < previousCuesSize; ++i) {
- // 10 - For each text track cue in other cues that has its text
- // track cue active flag set prepare an event named exit for the
- // TextTrackCue object with the text track cue end time.
- if (!currentCues.contains(previousCues[i]))
- eventTasks.append(std::make_pair(previousCues[i].data()->endTime(),
- previousCues[i].data()));
- }
-
- for (size_t i = 0; i < currentCuesSize; ++i) {
- // 11 - For each text track cue in current cues that does not have its
- // text track cue active flag set, prepare an event named enter for the
- // TextTrackCue object with the text track cue start time.
- if (!previousCues.contains(currentCues[i]))
- eventTasks.append(std::make_pair(currentCues[i].data()->startTime(),
- currentCues[i].data()));
- }
-
- // 12 - Sort the tasks in events in ascending time order (tasks with earlier
- // times first).
- nonCopyingSort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare);
-
- for (size_t i = 0; i < eventTasks.size(); ++i) {
- if (!affectedTracks.contains(eventTasks[i].second->track()))
- affectedTracks.append(eventTasks[i].second->track());
-
- // 13 - Queue each task in events, in list order.
- RefPtrWillBeRawPtr<Event> event = nullptr;
-
- // Each event in eventTasks may be either an enterEvent or an exitEvent,
- // depending on the time that is associated with the event. This
- // correctly identifies the type of the event, if the startTime is
- // less than the endTime in the cue.
- if (eventTasks[i].second->startTime() >= eventTasks[i].second->endTime()) {
- event = Event::create(EventTypeNames::enter);
- event->setTarget(eventTasks[i].second);
- m_asyncEventQueue->enqueueEvent(event.release());
-
- event = Event::create(EventTypeNames::exit);
- event->setTarget(eventTasks[i].second);
- m_asyncEventQueue->enqueueEvent(event.release());
- } else {
- if (eventTasks[i].first == eventTasks[i].second->startTime())
- event = Event::create(EventTypeNames::enter);
- else
- event = Event::create(EventTypeNames::exit);
-
- event->setTarget(eventTasks[i].second);
- m_asyncEventQueue->enqueueEvent(event.release());
- }
- }
-
- // 14 - Sort affected tracks in the same order as the text tracks appear in
- // the media element's list of text tracks, and remove duplicates.
- nonCopyingSort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare);
-
- // 15 - For each text track in affected tracks, in the list order, queue a
- // task to fire a simple event named cuechange at the TextTrack object, and, ...
- for (size_t i = 0; i < affectedTracks.size(); ++i) {
- RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::cuechange);
- event->setTarget(affectedTracks[i]);
-
- m_asyncEventQueue->enqueueEvent(event.release());
-
- // ... if the text track has a corresponding track element, to then fire a
- // simple event named cuechange at the track element as well.
- if (affectedTracks[i]->trackType() == TextTrack::TrackElement) {
- RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::cuechange);
- HTMLTrackElement* trackElement = static_cast<LoadableTextTrack*>(affectedTracks[i].get())->trackElement();
- ASSERT(trackElement);
- event->setTarget(trackElement);
-
- m_asyncEventQueue->enqueueEvent(event.release());
- }
- }
-
- // 16 - Set the text track cue active flag of all the cues in the current
- // cues, and unset the text track cue active flag of all the cues in the
- // other cues.
- for (size_t i = 0; i < currentCuesSize; ++i)
- currentCues[i].data()->setIsActive(true);
-
- for (size_t i = 0; i < previousCuesSize; ++i) {
- if (!currentCues.contains(previousCues[i]))
- previousCues[i].data()->setIsActive(false);
- }
-
- // Update the current active cues.
- m_currentlyActiveCues = currentCues;
-
- if (activeSetChanged)
- updateTextTrackDisplay();
-}
-
bool HTMLMediaElement::textTracksAreReady() const
{
// 4.8.10.12.1 Text track model
@@ -1443,7 +1166,7 @@ void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
track->setHasBeenConfigured(true);
if (track->mode() != TextTrack::disabledKeyword()) {
if (trackElement->readyState() == HTMLTrackElement::LOADED)
- textTrackAddCues(track, track->cues());
+ cueTimeline().addCues(track, track->cues());
// If this is the first added track, create the list of text tracks.
if (!m_textTracks)
@@ -1452,7 +1175,7 @@ void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
break;
}
} else if (track->trackType() == TextTrack::AddTrack && track->mode() != TextTrack::disabledKeyword()) {
- textTrackAddCues(track, track->cues());
+ cueTimeline().addCues(track, track->cues());
}
configureTextTrackDisplay(AssumeVisibleChange);
@@ -1467,78 +1190,6 @@ void HTMLMediaElement::textTrackKindChanged(TextTrack* track)
track->setMode(TextTrack::hiddenKeyword());
}
-void HTMLMediaElement::beginIgnoringTrackDisplayUpdateRequests()
-{
- ++m_ignoreTrackDisplayUpdate;
-}
-
-void HTMLMediaElement::endIgnoringTrackDisplayUpdateRequests()
-{
- ASSERT(m_ignoreTrackDisplayUpdate);
- --m_ignoreTrackDisplayUpdate;
- if (!m_ignoreTrackDisplayUpdate && inActiveDocument())
- updateActiveTextTrackCues(currentTime());
-}
-
-void HTMLMediaElement::textTrackAddCues(TextTrack* track, const TextTrackCueList* cues)
-{
- WTF_LOG(Media, "HTMLMediaElement::textTrackAddCues(%p)", this);
- ASSERT(track->mode() != TextTrack::disabledKeyword());
-
- TrackDisplayUpdateScope scope(this);
- for (size_t i = 0; i < cues->length(); ++i)
- textTrackAddCue(cues->item(i)->track(), cues->item(i));
-}
-
-void HTMLMediaElement::textTrackRemoveCues(TextTrack*, const TextTrackCueList* cues)
-{
- WTF_LOG(Media, "HTMLMediaElement::textTrackRemoveCues(%p)", this);
-
- TrackDisplayUpdateScope scope(this);
- for (size_t i = 0; i < cues->length(); ++i)
- textTrackRemoveCue(cues->item(i)->track(), cues->item(i));
-}
-
-void HTMLMediaElement::textTrackAddCue(TextTrack* track, PassRefPtrWillBeRawPtr<TextTrackCue> cue)
-{
- ASSERT(track->mode() != TextTrack::disabledKeyword());
-
- // Negative duration cues need be treated in the interval tree as
- // zero-length cues.
- double endTime = std::max(cue->startTime(), cue->endTime());
-
- CueInterval interval = m_cueTree.createInterval(cue->startTime(), endTime, cue.get());
- if (!m_cueTree.contains(interval))
- m_cueTree.add(interval);
- updateActiveTextTrackCues(currentTime());
-}
-
-void HTMLMediaElement::textTrackRemoveCue(TextTrack*, PassRefPtrWillBeRawPtr<TextTrackCue> cue)
-{
- // Negative duration cues need to be treated in the interval tree as
- // zero-length cues.
- double endTime = std::max(cue->startTime(), cue->endTime());
-
- CueInterval interval = m_cueTree.createInterval(cue->startTime(), endTime, cue.get());
- m_cueTree.remove(interval);
-
- // Since the cue will be removed from the media element and likely the
- // TextTrack might also be destructed, notifying the region of the cue
- // removal shouldn't be done.
- cue->notifyRegionWhenRemovingDisplayTree(false);
-
- size_t index = m_currentlyActiveCues.find(interval);
- if (index != kNotFound) {
- m_currentlyActiveCues.remove(index);
- cue->setIsActive(false);
- }
- cue->removeDisplayTree();
- updateActiveTextTrackCues(currentTime());
-
- cue->notifyRegionWhenRemovingDisplayTree(true);
-}
-
-
bool HTMLMediaElement::isSafeToLoadURL(const KURL& url, InvalidURLAction actionIfInvalid)
{
if (!url.isValid()) {
@@ -1929,7 +1580,7 @@ void HTMLMediaElement::setReadyState(ReadyState state)
updatePlayState();
updateMediaController();
- updateActiveTextTrackCues(currentTime());
+ cueTimeline().updateActiveCues(currentTime());
}
void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*)
@@ -2518,7 +2169,7 @@ void HTMLMediaElement::playbackProgressTimerFired(Timer<HTMLMediaElement>*)
if (!m_paused && hasMediaControls())
mediaControls()->playbackProgressed();
- updateActiveTextTrackCues(currentTime());
+ cueTimeline().updateActiveCues(currentTime());
}
void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent)
@@ -2728,7 +2379,7 @@ void HTMLMediaElement::addTextTrack(TextTrack* track)
void HTMLMediaElement::removeTextTrack(TextTrack* track)
{
- TrackDisplayUpdateScope scope(this);
+ TrackDisplayUpdateScope scope(this->cueTimeline());
m_textTracks->remove(track);
textTracksChanged();
@@ -2740,7 +2391,7 @@ void HTMLMediaElement::forgetResourceSpecificTracks()
// The order is explicitly specified as text, then audio, and finally video. Also
// 'removetrack' events should not be fired.
if (m_textTracks) {
- TrackDisplayUpdateScope scope(this);
+ TrackDisplayUpdateScope scope(this->cueTimeline());
m_textTracks->removeAllInbandTracks();
textTracksChanged();
}
@@ -3045,7 +2696,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged()
{
WTF_LOG(Media, "HTMLMediaElement::mediaPlayerTimeChanged(%p)", this);
- updateActiveTextTrackCues(currentTime());
+ cueTimeline().updateActiveCues(currentTime());
invalidateCachedTime();
@@ -3389,7 +3040,7 @@ void HTMLMediaElement::userCancelledLoad()
m_readyState = HAVE_NOTHING;
invalidateCachedTime();
updateMediaController();
- updateActiveTextTrackCues(0);
+ cueTimeline().updateActiveCues(0);
}
void HTMLMediaElement::clearMediaPlayerAndAudioSourceProviderClientWithoutLocking()
@@ -3688,6 +3339,13 @@ void HTMLMediaElement::configureMediaControls()
mediaControls()->hide();
}
+CueTimeline& HTMLMediaElement::cueTimeline()
+{
+ if (!m_cueTimeline)
+ m_cueTimeline = adoptPtrWillBeNoop(new CueTimeline(*this));
+ return *m_cueTimeline;
+}
+
void HTMLMediaElement::configureTextTrackDisplay(VisibilityChangeAssumption assumption)
{
ASSERT(m_textTracks);
@@ -3706,7 +3364,7 @@ void HTMLMediaElement::configureTextTrackDisplay(VisibilityChangeAssumption assu
if (assumption == AssumeNoVisibleChange
&& m_haveVisibleTextTrack == haveVisibleTextTrack) {
- updateActiveTextTrackCues(currentTime());
+ cueTimeline().updateActiveCues(currentTime());
return;
}
m_haveVisibleTextTrack = haveVisibleTextTrack;
@@ -3718,7 +3376,7 @@ void HTMLMediaElement::configureTextTrackDisplay(VisibilityChangeAssumption assu
ensureMediaControls();
mediaControls()->changedClosedCaptionsVisibility();
- updateActiveTextTrackCues(currentTime());
+ cueTimeline().updateActiveCues(currentTime());
updateTextTrackDisplay();
}
@@ -3928,6 +3586,7 @@ void HTMLMediaElement::trace(Visitor* visitor)
visitor->trace(m_mediaSource);
visitor->trace(m_audioTracks);
visitor->trace(m_videoTracks);
+ visitor->trace(m_cueTimeline);
visitor->trace(m_textTracks);
visitor->trace(m_textTracksWhenResourceSelectionBegan);
visitor->trace(m_mediaController);

Powered by Google App Engine
This is Rietveld 408576698