void TextTrackCueList::collectActiveCues(TextTrackCueList& activeCues) const
{
    activeCues.clear();
    for (auto& cue : m_list) {
        if (cue->isActive())
            activeCues.add(cue);
    }
}
Пример #2
0
unsigned TextTrackCue::cueIndex() {
  // This method can only be called on cues while they are associated with
  // a(n enabled) track (and hence that track's list of cues should exist.)
  DCHECK(track() && track()->cues());
  TextTrackCueList* cueList = track()->cues();
  if (!cueList->isCueIndexValid(m_cueIndex))
    cueList->validateCueIndexes();
  return m_cueIndex;
}
Пример #3
0
void
TextTrackManager::AddCues(TextTrack* aTextTrack)
{
  TextTrackCueList* cueList = aTextTrack->GetCues();
  if (cueList) {
    bool dummy;
    for (uint32_t i = 0; i < cueList->Length(); ++i) {
      mNewCues->AddCue(*cueList->IndexedGetter(i, dummy));
    }
  }
}
Пример #4
0
void TextTrack::addListOfCues(HeapVector<Member<TextTrackCue>>& listOfNewCues)
{
    TextTrackCueList* cues = ensureTextTrackCueList();

    for (auto& newCue : listOfNewCues) {
        newCue->setTrack(this);
        cues->add(newCue);
    }

    if (cueTimeline() && mode() != disabledKeyword())
        cueTimeline()->addCues(this, cues);
}
Пример #5
0
void
TextTrackManager::AddCues(TextTrack* aTextTrack)
{
  if (!mNewCues) {
    return;
  }

  TextTrackCueList* cueList = aTextTrack->GetCues();
  if (cueList) {
    bool dummy;
    for (uint32_t i = 0; i < cueList->Length(); ++i) {
      mNewCues->AddCue(*cueList->IndexedGetter(i, dummy));
    }
    DispatchTimeMarchesOn();
  }
}
Пример #6
0
void TextTrackManager::AddCues(TextTrack* aTextTrack) {
  if (!mNewCues) {
    WEBVTT_LOG("AddCues mNewCues is null");
    return;
  }

  TextTrackCueList* cueList = aTextTrack->GetCues();
  if (cueList) {
    bool dummy;
    WEBVTT_LOGV("AddCues, CuesNum=%d", cueList->Length());
    for (uint32_t i = 0; i < cueList->Length(); ++i) {
      mNewCues->AddCue(*cueList->IndexedGetter(i, dummy));
    }
    TimeMarchesOn();
  }
}
Пример #7
0
void
TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly)
{
  if (!mPendingTextTracks || !mTextTracks) {
    return;
  }

  mPendingTextTracks->RemoveTextTrack(aTextTrack);
  if (aPendingListOnly) {
    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) {
      mNewCues->RemoveCue(*((*removeCueList)[i]));
    }
    DispatchTimeMarchesOn();
  }
}
Пример #8
0
void TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack,
                                       bool aPendingListOnly) {
  if (!mPendingTextTracks || !mTextTracks) {
    return;
  }

  WEBVTT_LOG("RemoveTextTrack TextTrack %p", aTextTrack);
  mPendingTextTracks->RemoveTextTrack(aTextTrack);
  if (aPendingListOnly) {
    return;
  }

  mTextTracks->RemoveTextTrack(aTextTrack);
  // Remove the cues in mNewCues belong to aTextTrack.
  TextTrackCueList* removeCueList = aTextTrack->GetCues();
  if (removeCueList) {
    WEBVTT_LOGV("RemoveTextTrack removeCuesNum=%d",
                removeCueList->Length());
    for (uint32_t i = 0; i < removeCueList->Length(); ++i) {
      mNewCues->RemoveCue(*((*removeCueList)[i]));
    }
    TimeMarchesOn();
  }
}
Пример #9
0
// https://html.spec.whatwg.org/multipage/embedded-content.html#time-marches-on
void
TextTrackManager::TimeMarchesOn()
{
  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
  WEBVTT_LOG("TimeMarchesOn");
  mTimeMarchesOnDispatched = false;

  // Early return if we don't have any TextTracks or shutting down.
  if (!mTextTracks || mTextTracks->Length() == 0 || mShutdown) {
    return;
  }

  nsISupports* parentObject =
    mMediaElement->OwnerDoc()->GetParentObject();
  if (NS_WARN_IF(!parentObject)) {
    return;
  }
  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(parentObject);

  if (mMediaElement &&
      (!(mMediaElement->GetPlayedOrSeeked()) || mMediaElement->Seeking())) {
    WEBVTT_LOG("TimeMarchesOn seeking or post return");
    return;
  }

  // Step 3.
  double currentPlaybackTime = mMediaElement->CurrentTime();
  bool hasNormalPlayback = !mHasSeeked;
  mHasSeeked = false;
  WEBVTT_LOG("TimeMarchesOn mLastTimeMarchesOnCalled %lf currentPlaybackTime %lf hasNormalPlayback %d"
      , mLastTimeMarchesOnCalled, currentPlaybackTime, hasNormalPlayback);

  // Step 1, 2.
  RefPtr<TextTrackCueList> currentCues =
    new TextTrackCueList(window);
  RefPtr<TextTrackCueList> otherCues =
    new TextTrackCueList(window);
  bool dummy;
  for (uint32_t index = 0; index < mTextTracks->Length(); ++index) {
    TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
    if (ttrack && dummy) {
      // TODO: call GetCueListByTimeInterval on mNewCues?
      ttrack->UpdateActiveCueList();
      TextTrackCueList* activeCueList = ttrack->GetActiveCues();
      if (activeCueList) {
        for (uint32_t i = 0; i < activeCueList->Length(); ++i) {
          currentCues->AddCue(*((*activeCueList)[i]));
        }
      }
    }
  }
  WEBVTT_LOGV("TimeMarchesOn currentCues %d", currentCues->Length());
  // Populate otherCues with 'non-active" cues.
  if (hasNormalPlayback) {
    if (currentPlaybackTime < mLastTimeMarchesOnCalled) {
      // TODO: Add log and find the root cause why the
      // playback position goes backward.
      mLastTimeMarchesOnCalled = currentPlaybackTime;
    }
    media::Interval<double> interval(mLastTimeMarchesOnCalled,
                                     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];
    otherCues->RemoveCue(*cue);
  }
  WEBVTT_LOGV("TimeMarchesOn otherCues %d", otherCues->Length());
  // 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 &&
          cue->EndTime() <= currentPlaybackTime) {
        missedCues->AddCue(*cue);
      }
    }
  }
  WEBVTT_LOGV("TimeMarchesOn missedCues %d", missedCues->Length());
  // Step 5. Empty now.
  // TODO: Step 6: fire timeupdate?

  // Step 7. Abort steps if condition 1, 2, 3 are satisfied.
  // 1. All of the cues in current cues have their active flag set.
  // 2. None of the cues in other cues have their active flag set.
  // 3. Missed cues is empty.
  bool c1 = true;
  for (uint32_t i = 0; i < currentCues->Length(); ++i) {
    if (!(*currentCues)[i]->GetActive()) {
      c1 = false;
      break;
    }
  }
  bool c2 = true;
  for (uint32_t i = 0; i < otherCues->Length(); ++i) {
    if ((*otherCues)[i]->GetActive()) {
      c2 = false;
      break;
    }
  }
  bool c3 = (missedCues->Length() == 0);
  if (c1 && c2 && c3) {
    mLastTimeMarchesOnCalled = currentPlaybackTime;
    WEBVTT_LOG("TimeMarchesOn step 7 return, mLastTimeMarchesOnCalled %lf", mLastTimeMarchesOnCalled);
    return;
  }

  // Step 8. Respect PauseOnExit flag if not seek.
  if (hasNormalPlayback) {
    for (uint32_t i = 0; i < otherCues->Length(); ++i) {
      TextTrackCue* cue = (*otherCues)[i];
      if (cue && cue->PauseOnExit() && cue->GetActive()) {
        WEBVTT_LOG("TimeMarchesOn pause the MediaElement");
        mMediaElement->Pause();
        break;
      }
    }
    for (uint32_t i = 0; i < missedCues->Length(); ++i) {
      TextTrackCue* cue = (*missedCues)[i];
      if (cue && cue->PauseOnExit()) {
        WEBVTT_LOG("TimeMarchesOn pause the MediaElement");
        mMediaElement->Pause();
        break;
      }
    }
  }

  // Step 15.
  // Sort text tracks in the same order as the text tracks appear
  // in the media element's list of text tracks, and remove
  // duplicates.
  TextTrackListInternal affectedTracks;
  // Step 13, 14.
  nsTArray<RefPtr<SimpleTextTrackEvent>> eventList;
  // Step 9, 10.
  // For each text track cue in missed cues, prepare an event named
  // enter for the TextTrackCue object with the cue start time.
  for (uint32_t i = 0; i < missedCues->Length(); ++i) {
    TextTrackCue* cue = (*missedCues)[i];
    if (cue) {
      SimpleTextTrackEvent* event =
        new SimpleTextTrackEvent(NS_LITERAL_STRING("enter"),
                                 cue->StartTime(), cue->GetTrack(),
                                 cue);
      eventList.InsertElementSorted(event,
        CompareSimpleTextTrackEvents(mMediaElement));
      affectedTracks.AddTextTrack(cue->GetTrack(), CompareTextTracks(mMediaElement));
    }
  }

  // Step 11, 17.
  for (uint32_t i = 0; i < otherCues->Length(); ++i) {
    TextTrackCue* cue = (*otherCues)[i];
    if (cue->GetActive() || missedCues->IsCueExist(cue)) {
      double time = cue->StartTime() > cue->EndTime() ? cue->StartTime()
                                                      : cue->EndTime();
      SimpleTextTrackEvent* event =
        new SimpleTextTrackEvent(NS_LITERAL_STRING("exit"), time,
                                 cue->GetTrack(), cue);
      eventList.InsertElementSorted(event,
        CompareSimpleTextTrackEvents(mMediaElement));
      affectedTracks.AddTextTrack(cue->GetTrack(), CompareTextTracks(mMediaElement));
    }
    cue->SetActive(false);
  }

  // Step 12, 17.
  for (uint32_t i = 0; i < currentCues->Length(); ++i) {
    TextTrackCue* cue = (*currentCues)[i];
    if (!cue->GetActive()) {
      SimpleTextTrackEvent* event =
        new SimpleTextTrackEvent(NS_LITERAL_STRING("enter"),
                                 cue->StartTime(), cue->GetTrack(),
                                 cue);
      eventList.InsertElementSorted(event,
        CompareSimpleTextTrackEvents(mMediaElement));
      affectedTracks.AddTextTrack(cue->GetTrack(), CompareTextTracks(mMediaElement));
    }
    cue->SetActive(true);
  }

  // Fire the eventList
  for (uint32_t i = 0; i < eventList.Length(); ++i) {
    NS_DispatchToMainThread(eventList[i].forget());
  }

  // Step 16.
  for (uint32_t i = 0; i < affectedTracks.Length(); ++i) {
    TextTrack* ttrack = affectedTracks[i];
    if (ttrack) {
      ttrack->DispatchAsyncTrustedEvent(NS_LITERAL_STRING("cuechange"));
      HTMLTrackElement* trackElement = ttrack->GetTrackElement();
      if (trackElement) {
        trackElement->DispatchTrackRunnable(NS_LITERAL_STRING("cuechange"));
      }
    }
  }

  mLastTimeMarchesOnCalled = currentPlaybackTime;
  mLastActiveCues = currentCues;

  // Step 18.
  UpdateCueDisplay();
}
Пример #10
0
  bool LessThan(SimpleTextTrackEvent* aOne, SimpleTextTrackEvent* aTwo) const
  {
    // TimeMarchesOn step 13.1.
    if (aOne->mTime < aTwo->mTime) {
      return true;
    } else if (aOne->mTime > aTwo->mTime) {
      return false;
    }

    // TimeMarchesOn step 13.2 text track cue order.
    // TextTrack position in TextTrackList
    TextTrack* t1 = aOne->mTrack;
    TextTrack* t2 = aTwo->mTrack;
    MOZ_ASSERT(t1, "CompareSimpleTextTrackEvents t1 is null");
    MOZ_ASSERT(t2, "CompareSimpleTextTrackEvents t2 is null");
    if (t1 != t2) {
      TextTrackList* tList= t1->GetTextTrackList();
      MOZ_ASSERT(tList, "CompareSimpleTextTrackEvents tList is null");
      nsTArray<RefPtr<TextTrack>>& textTracks = tList->GetTextTrackArray();
      auto index1 = textTracks.IndexOf(t1);
      auto index2 = textTracks.IndexOf(t2);
      if (index1 < index2) {
        return true;
      } else if (index1 > index2) {
        return false;
      }
    }

    MOZ_ASSERT(t1 == t2, "CompareSimpleTextTrackEvents t1 != t2");
    // c1 and c2 are both belongs to t1.
    TextTrackCue* c1 = aOne->mCue;
    TextTrackCue* c2 = aTwo->mCue;
    if (c1 != c2) {
      if (c1->StartTime() < c2->StartTime()) {
        return true;
      } else if (c1->StartTime() > c2->StartTime()) {
        return false;
      }
      if (c1->EndTime() < c2->EndTime()) {
        return true;
      } else if (c1->EndTime() > c2->EndTime()) {
        return false;
      }

      TextTrackCueList* cueList = t1->GetCues();
      nsTArray<RefPtr<TextTrackCue>>& cues = cueList->GetCuesArray();
      auto index1 = cues.IndexOf(c1);
      auto index2 = cues.IndexOf(c2);
      if (index1 < index2) {
        return true;
      } else if (index1 > index2) {
        return false;
      }
    }

    // TimeMarchesOn step 13.3.
    if (aOne->mName.EqualsLiteral("enter") ||
        aTwo->mName.EqualsLiteral("exit")) {
      return true;
    }
    return false;
  }