Bug 882718 - 1. Fix testcase crash/failed . 2. The cuechange event should be fired in TimeMarchesOn. r=rillian
MozReview-Commit-ID: EYi9iZ1mfjg
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3743,23 +3743,23 @@ void HTMLMediaElement::SeekStarted()
{
DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
}
void HTMLMediaElement::SeekCompleted()
{
mPlayingBeforeSeek = false;
SetPlayedOrSeeked(true);
+ if (mTextTrackManager) {
+ mTextTrackManager->DidSeek();
+ }
FireTimeUpdate(false);
DispatchAsyncEvent(NS_LITERAL_STRING("seeked"));
// We changed whether we're seeking so we need to AddRemoveSelfReference
AddRemoveSelfReference();
- if (mTextTrackManager) {
- mTextTrackManager->DidSeek();
- }
if (mCurrentPlayRangeStart == -1.0) {
mCurrentPlayRangeStart = CurrentTime();
}
// Unset the variable on seekend
mPlayingThroughTheAudioChannelBeforeSeek = false;
}
void HTMLMediaElement::NotifySuspendedByCache(bool aIsSuspended)
--- a/dom/html/TextTrackManager.cpp
+++ b/dom/html/TextTrackManager.cpp
@@ -188,29 +188,31 @@ TextTrackManager::RemoveTextTrack(TextTr
return;
}
mTextTracks->RemoveTextTrack(aTextTrack);
// Remove the cues in mNewCues belong to aTextTrack.
TextTrackCueList* removeCueList = aTextTrack->GetCues();
if (removeCueList) {
for (uint32_t i = 0; i < removeCueList->Length(); ++i) {
- ErrorResult dummyRv;
- mNewCues->RemoveCue(*((*removeCueList)[i]), dummyRv);
+ mNewCues->RemoveCue(*((*removeCueList)[i]));
}
DispatchTimeMarchesOn();
}
}
void
TextTrackManager::DidSeek()
{
if (mTextTracks) {
mTextTracks->DidSeek();
}
+ if (mMediaElement) {
+ mLastTimeMarchesOnCalled = mMediaElement->CurrentTime();
+ }
mHasSeeked = true;
}
void
TextTrackManager::UpdateCueDisplay()
{
if (!mMediaElement || !mTextTracks) {
return;
@@ -259,18 +261,17 @@ TextTrackManager::AddCue(TextTrackCue& a
}
DispatchTimeMarchesOn();
}
void
TextTrackManager::NotifyCueRemoved(TextTrackCue& aCue)
{
if (mNewCues) {
- ErrorResult dummyRv;
- mNewCues->RemoveCue(aCue, dummyRv);
+ mNewCues->RemoveCue(aCue);
}
DispatchTimeMarchesOn();
}
void
TextTrackManager::PopulatePendingList()
{
if (!mTextTracks || !mPendingTextTracks || !mMediaElement) {
@@ -527,17 +528,18 @@ TextTrackManager::TimeMarchesOn()
nsISupports* parentObject =
mMediaElement->OwnerDoc()->GetParentObject();
if (NS_WARN_IF(!parentObject)) {
return;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(parentObject);
- if (mMediaElement && !(mMediaElement->GetPlayedOrSeeked())) {
+ if (mMediaElement &&
+ (!(mMediaElement->GetPlayedOrSeeked())|| mMediaElement->Seeking())) {
return;
}
// Step 3.
double currentPlaybackTime = mMediaElement->CurrentTime();
bool hasNormalPlayback = !mHasSeeked;
mHasSeeked = false;
@@ -565,18 +567,17 @@ TextTrackManager::TimeMarchesOn()
currentPlaybackTime);
otherCues = mNewCues->GetCueListByTimeInterval(interval);;
} else {
// Seek case. Put the mLastActiveCues into otherCues.
otherCues = mLastActiveCues;
}
for (uint32_t i = 0; i < currentCues->Length(); ++i) {
TextTrackCue* cue = (*currentCues)[i];
- ErrorResult dummy;
- otherCues->RemoveCue(*cue, dummy);
+ otherCues->RemoveCue(*cue);
}
// Step 4.
RefPtr<TextTrackCueList> missedCues = new TextTrackCueList(window);
if (hasNormalPlayback) {
for (uint32_t i = 0; i < otherCues->Length(); ++i) {
TextTrackCue* cue = (*otherCues)[i];
if (cue->StartTime() >= mLastTimeMarchesOnCalled &&
@@ -691,16 +692,20 @@ TextTrackManager::TimeMarchesOn()
NS_DispatchToMainThread(eventList[i].forget());
}
// Step 16.
for (uint32_t i = 0; i < affectedTracks.Length(); ++i) {
TextTrack* ttrack = affectedTracks[i];
if (ttrack) {
ttrack->DispatchTrustedEvent(NS_LITERAL_STRING("cuechange"));
+ HTMLTrackElement* trackElement = ttrack->GetTrackElement();
+ if (trackElement) {
+ trackElement->DispatchTrackRunnable(NS_LITERAL_STRING("cuechange"));
+ }
}
}
mLastTimeMarchesOnCalled = currentPlaybackTime;
mLastActiveCues = currentCues;
}
} // namespace dom
--- a/dom/media/TextTrack.cpp
+++ b/dom/media/TextTrack.cpp
@@ -124,23 +124,24 @@ TextTrack::AddCue(TextTrackCue& aCue)
}
}
SetDirty();
}
void
TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
{
- //TODO: Apply the rules for text track cue rendering Bug 865407
aCue.SetActive(false);
mCueList->RemoveCue(aCue, aRv);
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement) {
- mediaElement->NotifyCueRemoved(aCue);
+ if (mTextTrackList) {
+ HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
+ if (mediaElement) {
+ mediaElement->NotifyCueRemoved(aCue);
+ }
}
SetDirty();
}
void
TextTrack::SetCuesDirty()
{
for (uint32_t i = 0; i < mCueList->Length(); i++) {
@@ -155,56 +156,41 @@ TextTrack::UpdateActiveCueList()
return;
}
HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
if (!mediaElement) {
return;
}
- // Flag that indicates whether or not this call of UpdateActiveCueList has
- // changed the activeCueList.
- bool hasChanged = false;
-
// If we are dirty, i.e. an event happened that may cause the sorted mCueList
// to have changed like a seek or an insert for a cue, than we need to rebuild
// the active cue list from scratch.
if (mDirty) {
mCuePos = 0;
mDirty = false;
mActiveCueList->RemoveAll();
}
double playbackTime = mediaElement->CurrentTime();
// Remove all the cues from the active cue list whose end times now occur
// earlier then the current playback time.
for (uint32_t i = mActiveCueList->Length(); i > 0; i--) {
if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) {
mActiveCueList->RemoveCueAt(i - 1);
- hasChanged = true;
}
}
// Add all the cues, starting from the position of the last cue that was
// added, that have valid start and end times for the current playback time.
// We can stop iterating safely once we encounter a cue that does not have
// a valid start time as the cue list is sorted.
for (; mCuePos < mCueList->Length() &&
(*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) {
if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) {
mActiveCueList->AddCue(*(*mCueList)[mCuePos]);
- hasChanged = true;
- }
- }
-
- if (hasChanged) {
- RefPtr<AsyncEventDispatcher> asyncDispatcher =
- new AsyncEventDispatcher(this, NS_LITERAL_STRING("cuechange"), false);
- asyncDispatcher->PostDOMEvent();
- if (mTrackElement) {
- mTrackElement->DispatchTrackRunnable(NS_LITERAL_STRING("cuechange"));
}
}
}
TextTrackCueList*
TextTrack::GetActiveCues() {
if (mMode != TextTrackMode::Disabled) {
UpdateActiveCueList();
--- a/dom/media/TextTrackCueList.cpp
+++ b/dom/media/TextTrackCueList.cpp
@@ -99,16 +99,22 @@ TextTrackCueList::RemoveCue(TextTrackCue
if (!mList.Contains(&aCue)) {
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
return;
}
mList.RemoveElement(&aCue);
}
void
+TextTrackCueList::RemoveCue(TextTrackCue& aCue)
+{
+ mList.RemoveElement(&aCue);
+}
+
+void
TextTrackCueList::RemoveCueAt(uint32_t aIndex)
{
if (aIndex < mList.Length()) {
mList.RemoveElementAt(aIndex);
}
}
void
--- a/dom/media/TextTrackCueList.h
+++ b/dom/media/TextTrackCueList.h
@@ -45,16 +45,17 @@ public:
TextTrackCue* operator[](uint32_t aIndex);
TextTrackCue* GetCueById(const nsAString& aId);
TextTrackCueList& operator=(const TextTrackCueList& aOther);
// Adds a cue to mList by performing an insertion sort on mList.
// We expect most files to already be sorted, so an insertion sort starting
// from the end of the current array should be more efficient than a general
// sort step after all cues are loaded.
void AddCue(TextTrackCue& aCue);
+ void RemoveCue(TextTrackCue& aCue);
void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
void RemoveCueAt(uint32_t aIndex);
void RemoveAll();
void GetArray(nsTArray<RefPtr<TextTrackCue> >& aCues);
void SetCuesInactive();
already_AddRefed<TextTrackCueList>
--- a/dom/media/test/test_texttrackcue.html
+++ b/dom/media/test/test_texttrackcue.html
@@ -78,16 +78,20 @@ SpecialPowers.pushPrefEnv({"set": [["med
cue.id = "Cue 01";
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
cue.startTime = 0.51;
is(cue.startTime, 0.51, "Cue's start time should be 0.51.");
cue.endTime = 0.71;
is(cue.endTime, 0.71, "Cue's end time should be 0.71.");
cue.pauseOnExit = true;
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
+ video.addEventListener("pause", function pauseOnExit() {
+ video.removeEventListener("pause", pauseOnExit, false);
+ video.play();
+ });
var exceptionHappened;
function checkPercentageValue(prop) {
ok(prop in cue, prop + " should be a property on VTTCue.");
cue[prop] = 20;
is(cue[prop], 20, "Cue's " + prop + " should now be 20.");
[ 101, -1 ].forEach(function(val) {
exceptionHappened = false;