mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 883173 - Part 3: Implement TextTrack::ActiveCues. r=cpearce, r=rillian
- Active cues now returns the subset of cues in mCueList that are valid for the current playback time. - Introduces new code in media element, when seeking, and in TextTrack, when adding and removing cues, to mark the active cue list as dirty so that we know when we might need to rebuild the list completely.
This commit is contained in:
parent
cc4dfddc6f
commit
7141a09f73
@ -2938,6 +2938,7 @@ void HTMLMediaElement::SeekCompleted()
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("seeked"));
|
||||
// We changed whether we're seeking so we need to AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
mTextTracks->DidSeek();
|
||||
}
|
||||
|
||||
void HTMLMediaElement::NotifySuspendedByCache(bool aIsSuspended)
|
||||
@ -3866,7 +3867,7 @@ HTMLMediaElement::AddTextTrack(TextTrackKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aLanguage)
|
||||
{
|
||||
return mTextTracks->AddTextTrack(aKind, aLabel, aLanguage);
|
||||
return mTextTracks->AddTextTrack(this, aKind, aLabel, aLanguage);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -126,7 +126,7 @@ HTMLTrackElement::Track()
|
||||
if (!mTrack) {
|
||||
// We're expected to always have an internal TextTrack so create
|
||||
// an empty object to return if we don't already have one.
|
||||
mTrack = new TextTrack(OwnerDoc()->GetParentObject());
|
||||
mTrack = new TextTrack(OwnerDoc()->GetParentObject(), mMediaParent);
|
||||
}
|
||||
|
||||
return mTrack;
|
||||
@ -146,7 +146,8 @@ HTMLTrackElement::CreateTextTrack()
|
||||
kind = TextTrackKind::Subtitles;
|
||||
}
|
||||
|
||||
mTrack = new TextTrack(OwnerDoc()->GetParentObject(), kind, label, srcLang);
|
||||
mTrack = new TextTrack(OwnerDoc()->GetParentObject(), mMediaParent, kind,
|
||||
label, srcLang);
|
||||
|
||||
if (mMediaParent) {
|
||||
mMediaParent->AddTextTrack(mTrack);
|
||||
|
@ -6,16 +6,19 @@
|
||||
|
||||
#include "mozilla/dom/TextTrack.h"
|
||||
#include "mozilla/dom/TextTrackBinding.h"
|
||||
#include "mozilla/dom/TextTrackCue.h"
|
||||
#include "mozilla/dom/TextTrackCueList.h"
|
||||
#include "mozilla/dom/TextTrackRegion.h"
|
||||
#include "mozilla/dom/TextTrackRegionList.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(TextTrack,
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_5(TextTrack,
|
||||
nsDOMEventTargetHelper,
|
||||
mParent,
|
||||
mMediaElement,
|
||||
mCueList,
|
||||
mActiveCueList,
|
||||
mRegionList)
|
||||
@ -25,31 +28,46 @@ NS_IMPL_RELEASE_INHERITED(TextTrack, nsDOMEventTargetHelper)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
TextTrack::TextTrack(nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
TextTrack::TextTrack(nsISupports* aParent, HTMLMediaElement* aMediaElement)
|
||||
: mParent(aParent)
|
||||
, mMediaElement(aMediaElement)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
TextTrack::TextTrack(nsISupports* aParent,
|
||||
HTMLMediaElement* aMediaElement,
|
||||
TextTrackKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aLanguage)
|
||||
: mParent(aParent)
|
||||
, mKind(aKind)
|
||||
, mLabel(aLabel)
|
||||
, mLanguage(aLanguage)
|
||||
, mMode(TextTrackMode::Hidden)
|
||||
, mCueList(new TextTrackCueList(aParent))
|
||||
, mActiveCueList(new TextTrackCueList(aParent))
|
||||
, mRegionList(new TextTrackRegionList(aParent))
|
||||
, mMediaElement(aMediaElement)
|
||||
{
|
||||
SetDefaultSettings();
|
||||
mKind = aKind;
|
||||
mLabel = aLabel;
|
||||
mLanguage = aLanguage;
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
TextTrack::TextTrack(nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
, mKind(TextTrackKind::Subtitles)
|
||||
, mMode(TextTrackMode::Disabled)
|
||||
, mCueList(new TextTrackCueList(aParent))
|
||||
, mActiveCueList(new TextTrackCueList(aParent))
|
||||
, mRegionList(new TextTrackRegionList(aParent))
|
||||
void
|
||||
TextTrack::SetDefaultSettings()
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mKind = TextTrackKind::Subtitles;
|
||||
mMode = TextTrackMode::Hidden;
|
||||
mCueList = new TextTrackCueList(mParent);
|
||||
mActiveCueList = new TextTrackCueList(mParent);
|
||||
mRegionList = new TextTrackRegionList(mParent);
|
||||
mCuePos = 0;
|
||||
mDirty = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -74,12 +92,14 @@ void
|
||||
TextTrack::AddCue(TextTrackCue& aCue)
|
||||
{
|
||||
mCueList->AddCue(aCue);
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
void
|
||||
TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
|
||||
{
|
||||
mCueList->RemoveCue(aCue, aRv);
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
void
|
||||
@ -111,5 +131,43 @@ TextTrack::RemoveRegion(const TextTrackRegion& aRegion, ErrorResult& aRv)
|
||||
mRegionList->RemoveTextTrackRegion(aRegion);
|
||||
}
|
||||
|
||||
TextTrackCueList*
|
||||
TextTrack::GetActiveCues()
|
||||
{
|
||||
if (mMode == TextTrackMode::Disabled || !mMediaElement) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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 = true;
|
||||
mActiveCueList->RemoveAll();
|
||||
}
|
||||
|
||||
double playbackTime = mMediaElement->CurrentTime();
|
||||
// Remove all the cues from the active cue list whose end times now occur
|
||||
// earlier then the current playback time. When we reach a cue whose end time
|
||||
// is valid we can safely stop iterating as the list is sorted.
|
||||
for (uint32_t i = 0; i < mActiveCueList->Length() &&
|
||||
(*mActiveCueList)[i]->EndTime() < playbackTime; i++) {
|
||||
mActiveCueList->RemoveCueAt(i);
|
||||
}
|
||||
// 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
|
||||
// valid times for the current playback time as the cue list is sorted.
|
||||
for (; mCuePos < mCueList->Length(); mCuePos++) {
|
||||
TextTrackCue* cue = (*mCueList)[mCuePos];
|
||||
if (cue->StartTime() > playbackTime || cue->EndTime() < playbackTime) {
|
||||
break;
|
||||
}
|
||||
mActiveCueList->AddCue(*cue);
|
||||
}
|
||||
return mActiveCueList;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -20,6 +20,7 @@ class TextTrackCue;
|
||||
class TextTrackCueList;
|
||||
class TextTrackRegion;
|
||||
class TextTrackRegionList;
|
||||
class HTMLMediaElement;
|
||||
|
||||
class TextTrack MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
@ -29,10 +30,15 @@ public:
|
||||
|
||||
TextTrack(nsISupports* aParent);
|
||||
TextTrack(nsISupports* aParent,
|
||||
HTMLMediaElement* aMediaElement);
|
||||
TextTrack(nsISupports* aParent,
|
||||
HTMLMediaElement* aMediaElement,
|
||||
TextTrackKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aLanguage);
|
||||
|
||||
void SetDefaultSettings();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
@ -76,13 +82,7 @@ public:
|
||||
return mCueList;
|
||||
}
|
||||
|
||||
TextTrackCueList* GetActiveCues() const
|
||||
{
|
||||
if (mMode == TextTrackMode::Disabled) {
|
||||
return nullptr;
|
||||
}
|
||||
return mActiveCueList;
|
||||
}
|
||||
TextTrackCueList* GetActiveCues();
|
||||
|
||||
TextTrackRegionList* GetRegions() const
|
||||
{
|
||||
@ -101,11 +101,13 @@ public:
|
||||
void AddCue(TextTrackCue& aCue);
|
||||
void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
|
||||
void CueChanged(TextTrackCue& aCue);
|
||||
void SetDirty() { mDirty = true; }
|
||||
|
||||
IMPL_EVENT_HANDLER(cuechange)
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
nsRefPtr<HTMLMediaElement> mMediaElement;
|
||||
|
||||
TextTrackKind mKind;
|
||||
nsString mLabel;
|
||||
@ -117,6 +119,9 @@ private:
|
||||
nsRefPtr<TextTrackCueList> mCueList;
|
||||
nsRefPtr<TextTrackCueList> mActiveCueList;
|
||||
nsRefPtr<TextTrackRegionList> mRegionList;
|
||||
|
||||
uint32_t mCuePos;
|
||||
bool mDirty;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -62,6 +62,12 @@ TextTrackCueList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
return aFound ? mList[aIndex] : nullptr;
|
||||
}
|
||||
|
||||
TextTrackCue*
|
||||
TextTrackCueList::operator[](uint32_t aIndex)
|
||||
{
|
||||
return mList.SafeElementAt(aIndex, nullptr);
|
||||
}
|
||||
|
||||
TextTrackCue*
|
||||
TextTrackCueList::GetCueById(const nsAString& aId)
|
||||
{
|
||||
@ -96,5 +102,19 @@ TextTrackCueList::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
|
||||
mList.RemoveElement(&aCue);
|
||||
}
|
||||
|
||||
void
|
||||
TextTrackCueList::RemoveCueAt(uint32_t aIndex)
|
||||
{
|
||||
if (aIndex < mList.Length()) {
|
||||
mList.RemoveElementAt(aIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextTrackCueList::RemoveAll()
|
||||
{
|
||||
mList.Clear();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
void Update(double aTime);
|
||||
|
||||
TextTrackCue* IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
TextTrackCue* operator[](uint32_t aIndex);
|
||||
TextTrackCue* GetCueById(const nsAString& aId);
|
||||
|
||||
// Adds a cue to mList by performing an insertion sort on mList.
|
||||
@ -53,6 +54,8 @@ public:
|
||||
// sort step after all cues are loaded.
|
||||
void AddCue(TextTrackCue& aCue);
|
||||
void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
|
||||
void RemoveCueAt(uint32_t aIndex);
|
||||
void RemoveAll();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
@ -47,11 +47,13 @@ TextTrackList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
}
|
||||
|
||||
already_AddRefed<TextTrack>
|
||||
TextTrackList::AddTextTrack(TextTrackKind aKind,
|
||||
TextTrackList::AddTextTrack(HTMLMediaElement* aMediaElement,
|
||||
TextTrackKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aLanguage)
|
||||
{
|
||||
nsRefPtr<TextTrack> track = new TextTrack(mGlobal, aKind, aLabel, aLanguage);
|
||||
nsRefPtr<TextTrack> track = new TextTrack(mGlobal, aMediaElement, aKind,
|
||||
aLabel, aLanguage);
|
||||
mTextTracks.AppendElement(track);
|
||||
// TODO: dispatch addtrack event
|
||||
return track.forget();
|
||||
@ -76,5 +78,13 @@ TextTrackList::RemoveTextTrack(const TextTrack& aTrack)
|
||||
mTextTracks.RemoveElement(&aTrack);
|
||||
}
|
||||
|
||||
void
|
||||
TextTrackList::DidSeek()
|
||||
{
|
||||
for (uint32_t i = 0; i < mTextTracks.Length(); i++) {
|
||||
mTextTracks[i]->SetDirty();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
|
||||
TextTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
|
||||
already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
|
||||
already_AddRefed<TextTrack> AddTextTrack(HTMLMediaElement* aMediaElement,
|
||||
TextTrackKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aLanguage);
|
||||
TextTrack* GetTrackById(const nsAString& aId);
|
||||
@ -50,6 +51,7 @@ public:
|
||||
}
|
||||
|
||||
void RemoveTextTrack(const TextTrack& aTrack);
|
||||
void DidSeek();
|
||||
|
||||
IMPL_EVENT_HANDLER(addtrack)
|
||||
IMPL_EVENT_HANDLER(removetrack)
|
||||
|
Loading…
Reference in New Issue
Block a user