mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1818283: Make DOMMediaStream::TrackListener cycle-collected. r=pehrsons
This prevents HTMLMediaElements from being prematurely cycle-collected, and also makes things a bit safer. Differential Revision: https://phabricator.services.mozilla.com/D205734
This commit is contained in:
parent
647fcd0a58
commit
7fc0ce825d
@ -565,6 +565,10 @@ class HTMLMediaElement::MediaStreamTrackListener
|
||||
explicit MediaStreamTrackListener(HTMLMediaElement* aElement)
|
||||
: mElement(aElement) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamTrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override {
|
||||
if (!mElement) {
|
||||
return;
|
||||
@ -678,16 +682,26 @@ class HTMLMediaElement::MediaStreamTrackListener
|
||||
}
|
||||
|
||||
protected:
|
||||
const WeakPtr<HTMLMediaElement> mElement;
|
||||
virtual ~MediaStreamTrackListener() = default;
|
||||
RefPtr<HTMLMediaElement> mElement;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLMediaElement::MediaStreamTrackListener,
|
||||
DOMMediaStream::TrackListener, mElement)
|
||||
NS_IMPL_ADDREF_INHERITED(HTMLMediaElement::MediaStreamTrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_IMPL_RELEASE_INHERITED(HTMLMediaElement::MediaStreamTrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
|
||||
HTMLMediaElement::MediaStreamTrackListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream::TrackListener)
|
||||
|
||||
/**
|
||||
* Helper class that manages audio and video outputs for all enabled tracks in a
|
||||
* media element. It also manages calculating the current time when playing a
|
||||
* MediaStream.
|
||||
*/
|
||||
class HTMLMediaElement::MediaStreamRenderer
|
||||
: public DOMMediaStream::TrackListener {
|
||||
class HTMLMediaElement::MediaStreamRenderer {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(MediaStreamRenderer)
|
||||
|
||||
@ -1973,6 +1987,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLMediaElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement,
|
||||
nsGenericHTMLElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStreamWindowCapturer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcStream)
|
||||
@ -1988,6 +2003,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement,
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaStreamTrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncomingMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack)
|
||||
@ -2022,6 +2038,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement,
|
||||
tmp->mMediaStreamTrackListener.get());
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStreamWindowCapturer)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSrcStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSrcAttrStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
|
||||
@ -2040,6 +2057,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement,
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaStreamTrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncomingMediaKeys)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack)
|
||||
@ -5270,7 +5288,7 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream) {
|
||||
NotifyMediaStreamTrackAdded(track);
|
||||
}
|
||||
|
||||
mMediaStreamTrackListener = MakeUnique<MediaStreamTrackListener>(this);
|
||||
mMediaStreamTrackListener = new MediaStreamTrackListener(this);
|
||||
mSrcStream->RegisterTrackListener(mMediaStreamTrackListener.get());
|
||||
|
||||
ChangeNetworkState(NETWORK_IDLE);
|
||||
@ -7347,7 +7365,9 @@ void HTMLMediaElement::AudioCaptureTrackChange(bool aCapture) {
|
||||
CaptureStreamInternal(StreamCaptureBehavior::CONTINUE_WHEN_ENDED,
|
||||
StreamCaptureType::CAPTURE_AUDIO, mtg);
|
||||
mStreamWindowCapturer =
|
||||
MakeUnique<MediaStreamWindowCapturer>(stream, window->WindowID());
|
||||
new MediaStreamWindowCapturer(stream, window->WindowID());
|
||||
mStreamWindowCapturer->mStream->RegisterTrackListener(
|
||||
mStreamWindowCapturer);
|
||||
} else if (!aCapture && mStreamWindowCapturer) {
|
||||
for (size_t i = 0; i < mOutputStreams.Length(); i++) {
|
||||
if (mOutputStreams[i].mStream == mStreamWindowCapturer->mStream) {
|
||||
@ -7361,6 +7381,9 @@ void HTMLMediaElement::AudioCaptureTrackChange(bool aCapture) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mStreamWindowCapturer->mStream->UnregisterTrackListener(
|
||||
mStreamWindowCapturer);
|
||||
mStreamWindowCapturer = nullptr;
|
||||
if (mOutputStreams.IsEmpty()) {
|
||||
mTracksCaptured = nullptr;
|
||||
|
@ -1455,7 +1455,7 @@ class HTMLMediaElement : public nsGenericHTMLElement,
|
||||
|
||||
// Holds a reference to the stream connecting this stream to the window
|
||||
// capture sink.
|
||||
UniquePtr<MediaStreamWindowCapturer> mStreamWindowCapturer;
|
||||
RefPtr<MediaStreamWindowCapturer> mStreamWindowCapturer;
|
||||
|
||||
// Holds references to the DOM wrappers for the MediaStreams that we're
|
||||
// writing to.
|
||||
@ -1770,7 +1770,7 @@ class HTMLMediaElement : public nsGenericHTMLElement,
|
||||
|
||||
RefPtr<VideoTrackList> mVideoTrackList;
|
||||
|
||||
UniquePtr<MediaStreamTrackListener> mMediaStreamTrackListener;
|
||||
RefPtr<MediaStreamTrackListener> mMediaStreamTrackListener;
|
||||
|
||||
// The principal guarding mVideoFrameContainer access when playing a
|
||||
// MediaStream.
|
||||
|
@ -99,6 +99,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMediaStream,
|
||||
tmp->Destroy();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrackListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_PTR
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
@ -106,6 +107,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMMediaStream,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrackListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
||||
@ -115,6 +117,13 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(DOMMediaStream::TrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMMediaStream::TrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DOMMediaStream::DOMMediaStream(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow),
|
||||
mPlaybackTrackListener(MakeAndAddRef<PlaybackTrackListener>(this)) {
|
||||
|
@ -59,9 +59,10 @@ class DOMMediaStream : public DOMEventTargetHelper,
|
||||
public:
|
||||
typedef dom::MediaTrackConstraints MediaTrackConstraints;
|
||||
|
||||
class TrackListener {
|
||||
class TrackListener : public nsISupports {
|
||||
public:
|
||||
virtual ~TrackListener() = default;
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(TrackListener)
|
||||
|
||||
/**
|
||||
* Called when the DOMMediaStream has a live track added, either by
|
||||
@ -94,6 +95,9 @@ class DOMMediaStream : public DOMEventTargetHelper,
|
||||
* Called when the DOMMediaStream has become inaudible.
|
||||
*/
|
||||
virtual void NotifyInaudible(){};
|
||||
|
||||
protected:
|
||||
virtual ~TrackListener() = default;
|
||||
};
|
||||
|
||||
explicit DOMMediaStream(nsPIDOMWindowInner* aWindow);
|
||||
@ -236,7 +240,7 @@ class DOMMediaStream : public DOMEventTargetHelper,
|
||||
nsTArray<nsCOMPtr<nsISupports>> mConsumersToKeepAlive;
|
||||
|
||||
// The track listeners subscribe to changes in this stream's track set.
|
||||
nsTArray<TrackListener*> mTrackListeners;
|
||||
nsTArray<RefPtr<TrackListener>> mTrackListeners;
|
||||
|
||||
// True if this stream has live tracks.
|
||||
bool mActive = false;
|
||||
|
@ -569,7 +569,9 @@ void SelectBitrates(uint32_t aBitsPerSecond, uint8_t aNumVideoTracks,
|
||||
*/
|
||||
class MediaRecorder::Session : public PrincipalChangeObserver<MediaStreamTrack>,
|
||||
public DOMMediaStream::TrackListener {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Session)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Session,
|
||||
DOMMediaStream::TrackListener)
|
||||
|
||||
struct TrackTypeComparator {
|
||||
enum Type {
|
||||
@ -1170,6 +1172,14 @@ class MediaRecorder::Session : public PrincipalChangeObserver<MediaStreamTrack>,
|
||||
RefPtr<ShutdownBlocker> mShutdownBlocker;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRecorder::Session,
|
||||
DOMMediaStream::TrackListener, mMediaStream,
|
||||
mMediaStreamTracks)
|
||||
NS_IMPL_ADDREF_INHERITED(MediaRecorder::Session, DOMMediaStream::TrackListener)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaRecorder::Session, DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaRecorder::Session)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream::TrackListener)
|
||||
|
||||
MediaRecorder::~MediaRecorder() {
|
||||
LOG(LogLevel::Debug, ("~MediaRecorder (%p)", this));
|
||||
UnRegisterActivityObserver();
|
||||
|
@ -13,6 +13,15 @@ namespace mozilla {
|
||||
using dom::AudioStreamTrack;
|
||||
using dom::MediaStreamTrack;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaStreamWindowCapturer,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_IMPL_ADDREF_INHERITED(MediaStreamWindowCapturer,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaStreamWindowCapturer,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamWindowCapturer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream::TrackListener)
|
||||
|
||||
MediaStreamWindowCapturer::CapturedTrack::CapturedTrack(
|
||||
MediaStreamTrack* aTrack, uint64_t aWindowID)
|
||||
: mTrack(aTrack),
|
||||
@ -28,7 +37,6 @@ MediaStreamWindowCapturer::CapturedTrack::~CapturedTrack() {
|
||||
MediaStreamWindowCapturer::MediaStreamWindowCapturer(DOMMediaStream* aStream,
|
||||
uint64_t aWindowId)
|
||||
: mStream(aStream), mWindowId(aWindowId) {
|
||||
mStream->RegisterTrackListener(this);
|
||||
nsTArray<RefPtr<AudioStreamTrack>> tracks;
|
||||
mStream->GetAudioTracks(tracks);
|
||||
for (const auto& t : tracks) {
|
||||
@ -39,11 +47,7 @@ MediaStreamWindowCapturer::MediaStreamWindowCapturer(DOMMediaStream* aStream,
|
||||
}
|
||||
}
|
||||
|
||||
MediaStreamWindowCapturer::~MediaStreamWindowCapturer() {
|
||||
if (mStream) {
|
||||
mStream->UnregisterTrackListener(this);
|
||||
}
|
||||
}
|
||||
MediaStreamWindowCapturer::~MediaStreamWindowCapturer() = default;
|
||||
|
||||
void MediaStreamWindowCapturer::NotifyTrackAdded(
|
||||
const RefPtr<MediaStreamTrack>& aTrack) {
|
||||
|
@ -24,7 +24,9 @@ class MediaInputPort;
|
||||
class MediaStreamWindowCapturer : public DOMMediaStream::TrackListener {
|
||||
public:
|
||||
MediaStreamWindowCapturer(DOMMediaStream* aStream, uint64_t aWindowId);
|
||||
~MediaStreamWindowCapturer();
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamWindowCapturer,
|
||||
DOMMediaStream::TrackListener)
|
||||
|
||||
void NotifyTrackAdded(const RefPtr<dom::MediaStreamTrack>& aTrack) override;
|
||||
void NotifyTrackRemoved(const RefPtr<dom::MediaStreamTrack>& aTrack) override;
|
||||
@ -41,6 +43,7 @@ class MediaStreamWindowCapturer : public DOMMediaStream::TrackListener {
|
||||
const uint64_t mWindowId;
|
||||
|
||||
protected:
|
||||
~MediaStreamWindowCapturer();
|
||||
void AddTrack(dom::AudioStreamTrack* aTrack);
|
||||
void RemoveTrack(dom::AudioStreamTrack* aTrack);
|
||||
|
||||
|
@ -23,12 +23,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaStreamAudioSourceNode)
|
||||
tmp->Destroy();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInputStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInputTrack)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaStreamAudioSourceNode,
|
||||
AudioNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInputStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInputTrack)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamAudioSourceNode)
|
||||
@ -65,12 +67,13 @@ already_AddRefed<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::Create(
|
||||
|
||||
void MediaStreamAudioSourceNode::Init(DOMMediaStream& aMediaStream,
|
||||
ErrorResult& aRv) {
|
||||
mListener = new TrackListener(this);
|
||||
mInputStream = &aMediaStream;
|
||||
AudioNodeEngine* engine = new MediaStreamAudioSourceNodeEngine(this);
|
||||
mTrack = AudioNodeExternalInputTrack::Create(Context()->Graph(), engine);
|
||||
mInputStream->AddConsumerToKeepAlive(ToSupports(this));
|
||||
|
||||
mInputStream->RegisterTrackListener(this);
|
||||
mInputStream->RegisterTrackListener(mListener);
|
||||
if (mInputStream->Audible()) {
|
||||
NotifyAudible();
|
||||
}
|
||||
@ -79,8 +82,9 @@ void MediaStreamAudioSourceNode::Init(DOMMediaStream& aMediaStream,
|
||||
|
||||
void MediaStreamAudioSourceNode::Destroy() {
|
||||
if (mInputStream) {
|
||||
mInputStream->UnregisterTrackListener(this);
|
||||
mInputStream->UnregisterTrackListener(mListener);
|
||||
mInputStream = nullptr;
|
||||
mListener = nullptr;
|
||||
}
|
||||
DetachFromTrack();
|
||||
}
|
||||
@ -275,4 +279,14 @@ JSObject* MediaStreamAudioSourceNode::WrapObject(
|
||||
return MediaStreamAudioSourceNode_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaStreamAudioSourceNode::TrackListener,
|
||||
DOMMediaStream::TrackListener, mNode)
|
||||
NS_IMPL_ADDREF_INHERITED(MediaStreamAudioSourceNode::TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaStreamAudioSourceNode::TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
|
||||
MediaStreamAudioSourceNode::TrackListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream::TrackListener)
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -40,7 +40,6 @@ class MediaStreamAudioSourceNodeEngine final : public AudioNodeEngine {
|
||||
|
||||
class MediaStreamAudioSourceNode
|
||||
: public AudioNode,
|
||||
public DOMMediaStream::TrackListener,
|
||||
public PrincipalChangeObserver<MediaStreamTrack> {
|
||||
public:
|
||||
static already_AddRefed<MediaStreamAudioSourceNode> Create(
|
||||
@ -87,9 +86,28 @@ class MediaStreamAudioSourceNode
|
||||
ErrorResult& aRv);
|
||||
|
||||
// From DOMMediaStream::TrackListener.
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override;
|
||||
void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack) override;
|
||||
void NotifyAudible() override;
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack);
|
||||
void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack);
|
||||
void NotifyAudible();
|
||||
|
||||
class TrackListener final : public DOMMediaStream::TrackListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
explicit TrackListener(MediaStreamAudioSourceNode* aNode) : mNode(aNode) {}
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override {
|
||||
mNode->NotifyTrackAdded(aTrack);
|
||||
}
|
||||
void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack) override {
|
||||
mNode->NotifyTrackRemoved(aTrack);
|
||||
}
|
||||
void NotifyAudible() override { mNode->NotifyAudible(); }
|
||||
|
||||
private:
|
||||
virtual ~TrackListener() = default;
|
||||
RefPtr<MediaStreamAudioSourceNode> mNode;
|
||||
};
|
||||
|
||||
// From PrincipalChangeObserver<MediaStreamTrack>.
|
||||
void PrincipalChanged(MediaStreamTrack* aMediaStreamTrack) override;
|
||||
@ -120,6 +138,7 @@ class MediaStreamAudioSourceNode
|
||||
|
||||
// On construction we set this to the first audio track of mInputStream.
|
||||
RefPtr<MediaStreamTrack> mInputTrack;
|
||||
RefPtr<TrackListener> mListener;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -136,7 +136,7 @@ CreateSpeechRecognitionService(nsPIDOMWindowInner* aWindow,
|
||||
NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(SpeechRecognition,
|
||||
DOMEventTargetHelper, mStream,
|
||||
mTrack, mRecognitionService,
|
||||
mSpeechGrammarList)
|
||||
mSpeechGrammarList, mListener)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechRecognition)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
@ -145,6 +145,16 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
NS_IMPL_ADDREF_INHERITED(SpeechRecognition, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(SpeechRecognition, DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(SpeechRecognition::TrackListener,
|
||||
DOMMediaStream::TrackListener,
|
||||
mSpeechRecognition)
|
||||
NS_IMPL_ADDREF_INHERITED(SpeechRecognition::TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_IMPL_RELEASE_INHERITED(SpeechRecognition::TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechRecognition::TrackListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream::TrackListener)
|
||||
|
||||
SpeechRecognition::SpeechRecognition(nsPIDOMWindowInner* aOwnerWindow)
|
||||
: DOMEventTargetHelper(aOwnerWindow),
|
||||
mEndpointer(kSAMPLE_RATE),
|
||||
@ -472,8 +482,9 @@ void SpeechRecognition::Reset() {
|
||||
|
||||
++mStreamGeneration;
|
||||
if (mStream) {
|
||||
mStream->UnregisterTrackListener(this);
|
||||
mStream->UnregisterTrackListener(mListener);
|
||||
mStream = nullptr;
|
||||
mListener = nullptr;
|
||||
}
|
||||
mTrack = nullptr;
|
||||
mTrackIsOwned = false;
|
||||
@ -642,7 +653,8 @@ RefPtr<GenericNonExclusivePromise> SpeechRecognition::StopRecording() {
|
||||
if (mStream) {
|
||||
// Ensure we don't start recording because a track became available
|
||||
// before we get reset.
|
||||
mStream->UnregisterTrackListener(this);
|
||||
mStream->UnregisterTrackListener(mListener);
|
||||
mListener = nullptr;
|
||||
}
|
||||
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
@ -801,10 +813,13 @@ void SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream,
|
||||
MediaStreamConstraints constraints;
|
||||
constraints.mAudio.SetAsBoolean() = true;
|
||||
|
||||
MOZ_ASSERT(!mListener);
|
||||
mListener = new TrackListener(this);
|
||||
|
||||
if (aStream.WasPassed()) {
|
||||
mStream = &aStream.Value();
|
||||
mTrackIsOwned = false;
|
||||
mStream->RegisterTrackListener(this);
|
||||
mStream->RegisterTrackListener(mListener);
|
||||
nsTArray<RefPtr<AudioStreamTrack>> tracks;
|
||||
mStream->GetAudioTracks(tracks);
|
||||
for (const RefPtr<AudioStreamTrack>& track : tracks) {
|
||||
@ -839,7 +854,7 @@ void SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream,
|
||||
return;
|
||||
}
|
||||
mStream = std::move(aStream);
|
||||
mStream->RegisterTrackListener(this);
|
||||
mStream->RegisterTrackListener(mListener);
|
||||
for (const RefPtr<AudioStreamTrack>& track : tracks) {
|
||||
if (!track->Ended()) {
|
||||
NotifyTrackAdded(track);
|
||||
|
@ -52,7 +52,6 @@ LogModule* GetSpeechRecognitionLog();
|
||||
|
||||
class SpeechRecognition final : public DOMEventTargetHelper,
|
||||
public nsIObserver,
|
||||
public DOMMediaStream::TrackListener,
|
||||
public SupportsWeakPtr {
|
||||
public:
|
||||
explicit SpeechRecognition(nsPIDOMWindowInner* aOwnerWindow);
|
||||
@ -133,7 +132,24 @@ class SpeechRecognition final : public DOMEventTargetHelper,
|
||||
EVENT_COUNT
|
||||
};
|
||||
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override;
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack);
|
||||
|
||||
class TrackListener final : public DOMMediaStream::TrackListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TrackListener,
|
||||
DOMMediaStream::TrackListener)
|
||||
explicit TrackListener(SpeechRecognition* aSpeechRecognition)
|
||||
: mSpeechRecognition(aSpeechRecognition) {}
|
||||
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override {
|
||||
mSpeechRecognition->NotifyTrackAdded(aTrack);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~TrackListener() = default;
|
||||
RefPtr<SpeechRecognition> mSpeechRecognition;
|
||||
};
|
||||
|
||||
// aMessage should be valid UTF-8, but invalid UTF-8 byte sequences are
|
||||
// replaced with the REPLACEMENT CHARACTER on conversion to UTF-16.
|
||||
void DispatchError(EventType aErrorType,
|
||||
@ -266,6 +282,8 @@ class SpeechRecognition final : public DOMEventTargetHelper,
|
||||
// a conforming implementation.
|
||||
uint32_t mMaxAlternatives;
|
||||
|
||||
RefPtr<TrackListener> mListener;
|
||||
|
||||
void ProcessTestEventRequest(nsISupports* aSubject,
|
||||
const nsAString& aEventName);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user