Index: head/www/waterfox/Makefile =================================================================== --- head/www/waterfox/Makefile (revision 472000) +++ head/www/waterfox/Makefile (revision 472001) @@ -1,78 +1,78 @@ # $FreeBSD$ PORTNAME= waterfox DISTVERSION= 56.2.0-31 DISTVERSIONSUFFIX= -gf435a827f82ac -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= www ipv6 MAINTAINER= jbeich@FreeBSD.org COMMENT= Distilled fork of Firefox DEPRECATED= Temporary experiment EXPIRATION_DATE=2018-07-10 BUILD_DEPENDS= nspr>=4.16:devel/nspr \ nss>=3.32.1:security/nss \ icu>=59.1,1:devel/icu \ libevent>=2.1.8:devel/libevent \ harfbuzz>=1.4.7:print/harfbuzz \ graphite2>=1.3.10:graphics/graphite2 \ png>=1.6.31:graphics/png \ libvorbis>=1.3.5,3:audio/libvorbis \ libvpx>=1.5.0:multimedia/libvpx \ sqlite3>=3.19.3:databases/sqlite3 \ ${PYTHON_PKGNAMEPREFIX}sqlite3>0:databases/py-sqlite3@${PY_FLAVOR} \ v4l_compat>0:multimedia/v4l_compat \ autoconf-2.13:devel/autoconf213 \ yasm:devel/yasm \ zip:archivers/zip # soundtouch>=1.9.0:audio/soundtouch \ LIB_DEPENDS= libv4l2.so:multimedia/libv4l USE_GITHUB= yes GH_ACCOUNT= MrAlex94 GH_PROJECT= Waterfox USE_GECKO= gecko MOZ_PKGCONFIG_FILES= # empty USE_MOZILLA= -soundtouch MOZILLA_NAME= Waterfox USE_GL= gl WATERFOX_ICON= ${MOZILLA}.png WATERFOX_ICON_SRC= ${PREFIX}/lib/${MOZILLA}/browser/chrome/icons/default/default256.png WATERFOX_DESKTOP= ${MOZSRC}/taskcluster/docker/firefox-snap/firefox.desktop MOZ_OPTIONS= --enable-application=browser \ --with-app-name=${MOZILLA} \ --with-app-basename=${MOZILLA_NAME} \ --with-distribution-id=org.${MOZILLA}project OPTIONS_DEFAULT= BUNDLED_CAIRO .include "${.CURDIR}/../../www/firefox/Makefile.options" # Inconsistent fallback order (libcubeb vs. audio_device) SNDIO_PREVENTS= ${OPTIONS_MULTI_AUDIO:NSNDIO} post-patch: @${REINPLACE_CMD} -e 's/%u/%U/' -e '/X-MultipleArgs/d' \ -e 's/firefox/${MOZILLA}/' \ -e 's/Firefox/${MOZILLA_NAME}/' \ ${WATERFOX_DESKTOP} @${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|g' \ ${WRKSRC}/browser/app/nsBrowserApp.cpp pre-configure: (cd ${WRKSRC} && ${LOCALBASE}/bin/autoconf-2.13) (cd ${WRKSRC}/js/src/ && ${LOCALBASE}/bin/autoconf-2.13) post-install: ${INSTALL_DATA} ${WATERFOX_DESKTOP} \ ${STAGEDIR}${PREFIX}/share/applications/${MOZILLA}.desktop ${MKDIR} ${STAGEDIR}${PREFIX}/share/pixmaps ${LN} -sf ${WATERFOX_ICON_SRC} ${STAGEDIR}${PREFIX}/share/pixmaps/${WATERFOX_ICON} .include Index: head/www/waterfox/files/patch-bug1453127 =================================================================== --- head/www/waterfox/files/patch-bug1453127 (revision 472000) +++ head/www/waterfox/files/patch-bug1453127 (revision 472001) @@ -1,605 +1,641 @@ +commit 7f8f5d958ed6 +Author: Bryce Van Dyk +Date: Wed Apr 18 15:30:57 2018 -0400 + + Bug 1453127 - Do not use iterators in MediaStreamTrack when removing listeners. r=pehrsons a=lizzard + + --HG-- + extra : source : 6b3aaee40f7507e240da08d6e073cff3c53971f4 +--- + dom/media/MediaStreamTrack.cpp | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git dom/media/MediaStreamTrack.cpp dom/media/MediaStreamTrack.cpp +index 010373e9086dc..af6c6014cf02a 100644 +--- dom/media/MediaStreamTrack.cpp ++++ dom/media/MediaStreamTrack.cpp +@@ -166,11 +166,15 @@ MediaStreamTrack::Destroy() + mPrincipalHandleListener->Forget(); + mPrincipalHandleListener = nullptr; + } +- for (auto l : mTrackListeners) { +- RemoveListener(l); ++ // Remove all listeners -- avoid iterating over the list we're removing from ++ const nsTArray> trackListeners(mTrackListeners); ++ for (auto listener : trackListeners) { ++ RemoveListener(listener); + } +- for (auto l : mDirectTrackListeners) { +- RemoveDirectListener(l); ++ // Do the same as above for direct listeners ++ const nsTArray> directTrackListeners(mDirectTrackListeners); ++ for (auto listener : directTrackListeners) { ++ RemoveDirectListener(listener); + } + } + commit 890e77744a2a Author: Andreas Pehrson Date: Tue May 29 10:13:14 2018 +0200 Bug 1453127 - Make sure decoder-captured tracks end when changing src. r=jya, a=RyanVM --- dom/html/HTMLMediaElement.cpp | 18 ++++++++++++++++++ dom/html/HTMLMediaElement.h | 5 +++++ 2 files changed, 23 insertions(+) diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp index b0e787fbf9278..d1502cecfb237 100644 --- dom/html/HTMLMediaElement.cpp +++ dom/html/HTMLMediaElement.cpp @@ -1429,6 +1429,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError) for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mPreCreatedTracks) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager) @@ -3494,6 +3495,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, RefPtr track = out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO, trackSource); + out->mPreCreatedTracks.AppendElement(track); out->mStream->AddTrackInternal(track); LOG(LogLevel::Debug, ("Created audio track %d for captured decoder", audioTrackId)); @@ -3505,6 +3507,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, RefPtr track = out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO, trackSource); + out->mPreCreatedTracks.AppendElement(track); out->mStream->AddTrackInternal(track); LOG(LogLevel::Debug, ("Created video track %d for captured decoder", videoTrackId)); @@ -7526,6 +7529,21 @@ HTMLMediaElement::RemoveMediaTracks() } mMediaTracksConstructed = false; + + for (OutputMediaStream& ms : mOutputStreams) { + if (!ms.mCapturingDecoder) { + continue; + } + for (RefPtr& t : ms.mPreCreatedTracks) { + if (t->Ended()) { + continue; + } + mAbstractMainThread->Dispatch(NewRunnableMethod( + "dom::HTMLMediaElement::RemoveMediaTracks", + t, &MediaStreamTrack::OverrideEnded)); + } + ms.mPreCreatedTracks.Clear(); + } } class MediaElementGMPCrashHelper : public GMPCrashHelper diff --git dom/html/HTMLMediaElement.h dom/html/HTMLMediaElement.h index a81a2dfb22f39..126aaee2ae655 100644 --- dom/html/HTMLMediaElement.h +++ dom/html/HTMLMediaElement.h @@ -843,6 +843,11 @@ protected: bool mCapturingDecoder; bool mCapturingMediaStream; + // The following members are keeping state for a captured MediaDecoder. + // Tracks that were created on main thread before MediaDecoder fed them + // to the MediaStreamGraph. + nsTArray> mPreCreatedTracks; + // The following members are keeping state for a captured MediaStream. TrackID mNextAvailableTrackID; nsTArray>> mTrackPorts; commit dee1e1ec98be Author: Andreas Pehrson Date: Tue May 29 10:21:51 2018 +0200 Bug 1453127 - Ensure TrackID uniqueness for captured MediaDecoder. r=jya, a=RyanVM --- dom/html/HTMLMediaElement.cpp | 22 +++++++--- dom/html/HTMLMediaElement.h | 2 +- dom/media/MediaDecoder.cpp | 13 +++++- dom/media/MediaDecoder.h | 3 ++ dom/media/MediaDecoderStateMachine.cpp | 10 ++++- dom/media/MediaDecoderStateMachine.h | 5 ++- dom/media/mediasink/DecodedStream.cpp | 11 +++-- dom/media/mediasink/OutputStreamManager.cpp | 68 ++++++++++++++++++++++------- dom/media/mediasink/OutputStreamManager.h | 33 ++++++++++---- 9 files changed, 131 insertions(+), 36 deletions(-) diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp index d1502cecfb237..d11c9d03a7e52 100644 --- dom/html/HTMLMediaElement.cpp +++ dom/html/HTMLMediaElement.cpp @@ -1710,6 +1710,14 @@ void HTMLMediaElement::ShutdownDecoder() if (mMediaSource) { mMediaSource->CompletePendingTransactions(); } + for (OutputMediaStream& out : mOutputStreams) { + if (!out.mCapturingDecoder) { + continue; + } + out.mNextAvailableTrackID = std::max( + mDecoder->NextAvailableTrackIDFor(out.mStream->GetInputStream()), + out.mNextAvailableTrackID); + } mDecoder->Shutdown(); mDecoder = nullptr; } @@ -3476,6 +3484,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, if (mDecoder) { out->mCapturingDecoder = true; mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(), + out->mNextAvailableTrackID, aFinishWhenEnded); } else if (mSrcStream) { out->mCapturingMediaStream = true; @@ -3489,11 +3498,12 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, if (mDecoder) { if (HasAudio()) { - TrackID audioTrackId = mMediaInfo.mAudio.mTrackId; + TrackID audioTrackId = out->mNextAvailableTrackID++; RefPtr trackSource = getter->GetMediaStreamTrackSource(audioTrackId); RefPtr track = - out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO, + out->mStream->CreateDOMTrack(audioTrackId, + MediaSegment::AUDIO, trackSource); out->mPreCreatedTracks.AppendElement(track); out->mStream->AddTrackInternal(track); @@ -3501,7 +3511,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, ("Created audio track %d for captured decoder", audioTrackId)); } if (IsVideo() && HasVideo() && !out->mCapturingAudioOnly) { - TrackID videoTrackId = mMediaInfo.mVideo.mTrackId; + TrackID videoTrackId = out->mNextAvailableTrackID++; RefPtr trackSource = getter->GetMediaStreamTrackSource(videoTrackId); RefPtr track = @@ -4241,11 +4251,12 @@ HTMLMediaElement::WakeLockRelease() } HTMLMediaElement::OutputMediaStream::OutputMediaStream() - : mFinishWhenEnded(false) + : mNextAvailableTrackID(1) + , mFinishWhenEnded(false) , mCapturingAudioOnly(false) , mCapturingDecoder(false) , mCapturingMediaStream(false) - , mNextAvailableTrackID(1) {} +{} HTMLMediaElement::OutputMediaStream::~OutputMediaStream() { @@ -4844,6 +4855,7 @@ HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder) ms.mCapturingDecoder = true; aDecoder->AddOutputStream(ms.mStream->GetInputStream()->AsProcessedStream(), + ms.mNextAvailableTrackID, ms.mFinishWhenEnded); } diff --git dom/html/HTMLMediaElement.h dom/html/HTMLMediaElement.h index 126aaee2ae655..aeccfa5ba221d 100644 --- dom/html/HTMLMediaElement.h +++ dom/html/HTMLMediaElement.h @@ -838,6 +838,7 @@ protected: ~OutputMediaStream(); RefPtr mStream; + TrackID mNextAvailableTrackID; bool mFinishWhenEnded; bool mCapturingAudioOnly; bool mCapturingDecoder; @@ -849,7 +850,6 @@ protected: nsTArray> mPreCreatedTracks; // The following members are keeping state for a captured MediaStream. - TrackID mNextAvailableTrackID; nsTArray>> mTrackPorts; }; diff --git dom/media/MediaDecoder.cpp dom/media/MediaDecoder.cpp index c4bf14d1206fd..11d48fb9921c1 100644 --- dom/media/MediaDecoder.cpp +++ dom/media/MediaDecoder.cpp @@ -322,11 +322,13 @@ MediaDecoder::SetVolume(double aVolume) void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load()."); - mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded); + mDecoderStateMachine->AddOutputStream( + aStream, aNextAvailableTrackID, aFinishWhenEnded); } void @@ -337,6 +339,14 @@ MediaDecoder::RemoveOutputStream(MediaStream* aStream) mDecoderStateMachine->RemoveOutputStream(aStream); } +TrackID +MediaDecoder::NextAvailableTrackIDFor(MediaStream* aOutputStream) const +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load()."); + return mDecoderStateMachine->NextAvailableTrackIDFor(aOutputStream); +} + double MediaDecoder::GetDuration() { diff --git dom/media/MediaDecoder.h dom/media/MediaDecoder.h index a8708b390433a..357f87ef8e0e8 100644 --- dom/media/MediaDecoder.h +++ dom/media/MediaDecoder.h @@ -183,9 +183,12 @@ public: // The stream is initially blocked. The decoder is responsible for unblocking // it while it is playing back. virtual void AddOutputStream(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, bool aFinishWhenEnded); // Remove an output stream added with AddOutputStream. virtual void RemoveOutputStream(MediaStream* aStream); + // The next TrackID that can be used without risk of a collision. + virtual TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; // Return the duration of the video in seconds. virtual double GetDuration(); diff --git dom/media/MediaDecoderStateMachine.cpp dom/media/MediaDecoderStateMachine.cpp index cea333f5d9a05..fef3b318b48cb 100644 --- dom/media/MediaDecoderStateMachine.cpp +++ dom/media/MediaDecoderStateMachine.cpp @@ -3973,11 +3973,12 @@ MediaDecoderStateMachine::RequestDebugInfo() } void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); LOG("AddOutputStream aStream=%p!", aStream); - mOutputStreamManager->Add(aStream, aFinishWhenEnded); + mOutputStreamManager->Add(aStream, aNextAvailableTrackID, aFinishWhenEnded); nsCOMPtr r = NewRunnableMethod("MediaDecoderStateMachine::SetAudioCaptured", this, @@ -4001,6 +4002,13 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream) } } +TrackID +MediaDecoderStateMachine::NextAvailableTrackIDFor(MediaStream* aOutputStream) const +{ + MOZ_ASSERT(NS_IsMainThread()); + return mOutputStreamManager->NextAvailableTrackIDFor(aOutputStream); +} + class VideoQueueMemoryFunctor : public nsDequeFunctor { public: diff --git dom/media/MediaDecoderStateMachine.h dom/media/MediaDecoderStateMachine.h index 6f7fcf825ea83..b59bcca7dc70a 100644 --- dom/media/MediaDecoderStateMachine.h +++ dom/media/MediaDecoderStateMachine.h @@ -175,9 +175,12 @@ public: RefPtr RequestDebugInfo(); - void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded); + void AddOutputStream(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, + bool aFinishWhenEnded); // Remove an output stream added with AddOutputStream. void RemoveOutputStream(MediaStream* aStream); + TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; // Seeks to the decoder to aTarget asynchronously. RefPtr InvokeSeek(const SeekTarget& aTarget); diff --git dom/media/mediasink/DecodedStream.cpp dom/media/mediasink/DecodedStream.cpp index 5244a087c77e7..b5c40b9067e57 100644 --- dom/media/mediasink/DecodedStream.cpp +++ dom/media/mediasink/DecodedStream.cpp @@ -193,17 +193,22 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager, , mAbstractMainThread(aMainThread) { mStream->AddListener(mListener); - mOutputStreamManager->Connect(mStream); + TrackID audioTrack = TRACK_NONE; + TrackID videoTrack = TRACK_NONE; // Initialize tracks. if (aInit.mInfo.HasAudio()) { - mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId, + audioTrack = aInit.mInfo.mAudio.mTrackId; + mStream->AddAudioTrack(audioTrack, aInit.mInfo.mAudio.mRate, 0, new AudioSegment()); } if (aInit.mInfo.HasVideo()) { - mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment()); + videoTrack = aInit.mInfo.mVideo.mTrackId; + mStream->AddTrack(videoTrack, 0, new VideoSegment()); } + + mOutputStreamManager->Connect(mStream, audioTrack, videoTrack); } DecodedStreamData::~DecodedStreamData() diff --git dom/media/mediasink/OutputStreamManager.cpp dom/media/mediasink/OutputStreamManager.cpp index d5685837a6783..b3ec8936d435e 100644 --- dom/media/mediasink/OutputStreamManager.cpp +++ dom/media/mediasink/OutputStreamManager.cpp @@ -13,29 +13,41 @@ OutputStreamData::~OutputStreamData() { MOZ_ASSERT(NS_IsMainThread()); // Break the connection to the input stream if necessary. - if (mPort) { - mPort->Destroy(); + for (RefPtr& port : mPorts) { + port->Destroy(); } } void -OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream) +OutputStreamData::Init(OutputStreamManager* aOwner, + ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID) { mOwner = aOwner; mStream = aStream; + mNextAvailableTrackID = aNextAvailableTrackID; } bool -OutputStreamData::Connect(MediaStream* aStream) +OutputStreamData::Connect(MediaStream* aStream, + TrackID aInputAudioTrackID, + TrackID aInputVideoTrackID) { MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mPort, "Already connected?"); + MOZ_ASSERT(mPorts.IsEmpty(), "Already connected?"); if (mStream->IsDestroyed()) { return false; } - mPort = mStream->AllocateInputPort(aStream); + for (TrackID tid : {aInputAudioTrackID, aInputVideoTrackID}) { + if (tid == TRACK_NONE) { + continue; + } + MOZ_ASSERT(IsTrackIDExplicit(tid)); + mPorts.AppendElement(mStream->AllocateInputPort( + aStream, tid, mNextAvailableTrackID++)); + } return true; } @@ -51,11 +63,11 @@ OutputStreamData::Disconnect() return false; } - // Disconnect the existing port if necessary. - if (mPort) { - mPort->Destroy(); - mPort = nullptr; + // Disconnect any existing port. + for (RefPtr& port : mPorts) { + port->Destroy(); } + mPorts.Clear(); return true; } @@ -71,8 +83,16 @@ OutputStreamData::Graph() const return mStream->Graph(); } +TrackID +OutputStreamData::NextAvailableTrackID() const +{ + return mNextAvailableTrackID; +} + void -OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded) +OutputStreamManager::Add(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, + bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); // All streams must belong to the same graph. @@ -84,12 +104,12 @@ OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded) } OutputStreamData* p = mStreams.AppendElement(); - p->Init(this, aStream); + p->Init(this, aStream, aNextAvailableTrackID); // Connect to the input stream if we have one. Otherwise the output stream // will be connected in Connect(). if (mInputStream) { - p->Connect(mInputStream); + p->Connect(mInputStream, mInputAudioTrackID, mInputVideoTrackID); } } @@ -105,13 +125,29 @@ OutputStreamManager::Remove(MediaStream* aStream) } } +TrackID +OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const +{ + MOZ_ASSERT(NS_IsMainThread()); + for (const OutputStreamData& out : mStreams) { + if (out.Equals(aOutputStream)) { + return out.NextAvailableTrackID(); + } + } + return TRACK_INVALID; +} + void -OutputStreamManager::Connect(MediaStream* aStream) +OutputStreamManager::Connect(MediaStream* aStream, + TrackID aAudioTrackID, + TrackID aVideoTrackID) { MOZ_ASSERT(NS_IsMainThread()); mInputStream = aStream; + mInputAudioTrackID = aAudioTrackID; + mInputVideoTrackID = aVideoTrackID; for (int32_t i = mStreams.Length() - 1; i >= 0; --i) { - if (!mStreams[i].Connect(aStream)) { + if (!mStreams[i].Connect(aStream, mInputAudioTrackID, mInputVideoTrackID)) { // Probably the DOMMediaStream was GCed. Clean up. mStreams.RemoveElementAt(i); } @@ -123,6 +159,8 @@ OutputStreamManager::Disconnect() { MOZ_ASSERT(NS_IsMainThread()); mInputStream = nullptr; + mInputAudioTrackID = TRACK_INVALID; + mInputVideoTrackID = TRACK_INVALID; for (int32_t i = mStreams.Length() - 1; i >= 0; --i) { if (!mStreams[i].Disconnect()) { // Probably the DOMMediaStream was GCed. Clean up. diff --git dom/media/mediasink/OutputStreamManager.h dom/media/mediasink/OutputStreamManager.h index 7f91a60c1e9dd..8e89878e45090 100644 --- dom/media/mediasink/OutputStreamManager.h +++ dom/media/mediasink/OutputStreamManager.h @@ -9,6 +9,7 @@ #include "mozilla/RefPtr.h" #include "nsTArray.h" +#include "MediaSegment.h" namespace mozilla { @@ -21,11 +22,13 @@ class ProcessedMediaStream; class OutputStreamData { public: ~OutputStreamData(); - void Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream); + void Init(OutputStreamManager* aOwner, + ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID); - // Connect mStream to the input stream. + // Connect the given input stream's audio and video tracks to mStream. // Return false is mStream is already destroyed, otherwise true. - bool Connect(MediaStream* aStream); + bool Connect(MediaStream* aStream, TrackID aAudioTrackID, TrackID aVideoTrackID); // Disconnect mStream from its input stream. // Return false is mStream is already destroyed, otherwise true. bool Disconnect(); @@ -34,12 +37,16 @@ public: bool Equals(MediaStream* aStream) const; // Return the graph mStream belongs to. MediaStreamGraph* Graph() const; + // The next TrackID that will not cause a collision in mStream. + TrackID NextAvailableTrackID() const; private: OutputStreamManager* mOwner; RefPtr mStream; - // mPort connects our mStream to an input stream. - RefPtr mPort; + // mPort connects an input stream to our mStream. + nsTArray> mPorts; + // For guaranteeing TrackID uniqueness in our mStream. + TrackID mNextAvailableTrackID = TRACK_INVALID; }; class OutputStreamManager { @@ -47,18 +54,24 @@ class OutputStreamManager { public: // Add the output stream to the collection. - void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded); + void Add(ProcessedMediaStream* aStream, + TrackID aNextAvailableTrackID, + bool aFinishWhenEnded); // Remove the output stream from the collection. void Remove(MediaStream* aStream); + // The next TrackID that will not cause a collision in aOutputStream. + TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; // Return true if the collection empty. bool IsEmpty() const { MOZ_ASSERT(NS_IsMainThread()); return mStreams.IsEmpty(); } - // Connect all output streams in the collection to the input stream. - void Connect(MediaStream* aStream); - // Disconnect all output streams from the input stream. + // Connect the given input stream's tracks to all output streams. + void Connect(MediaStream* aStream, + TrackID aAudioTrackID, + TrackID aVideoTrackID); + // Disconnect the input stream to all output streams. void Disconnect(); // Return the graph these streams belong to or null if empty. MediaStreamGraph* Graph() const @@ -72,6 +85,8 @@ private: // Keep the input stream so we can connect the output streams that // are added after Connect(). RefPtr mInputStream; + TrackID mInputAudioTrackID = TRACK_INVALID; + TrackID mInputVideoTrackID = TRACK_INVALID; nsTArray mStreams; }; commit 91317ba976c8 Author: Andreas Pehrson Date: Wed May 30 10:44:56 2018 +0200 Bug 1453127 - Clear output streams on shutdown. r=jya, a=RyanVM --- dom/media/MediaDecoderStateMachine.cpp | 4 ++++ dom/media/mediasink/OutputStreamManager.cpp | 7 +++++++ dom/media/mediasink/OutputStreamManager.h | 2 ++ 3 files changed, 13 insertions(+) diff --git dom/media/MediaDecoderStateMachine.cpp dom/media/MediaDecoderStateMachine.cpp index fef3b318b48cb..582fe7ba995fe 100644 --- dom/media/MediaDecoderStateMachine.cpp +++ dom/media/MediaDecoderStateMachine.cpp @@ -3564,6 +3564,10 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame() RefPtr MediaDecoderStateMachine::BeginShutdown() { + MOZ_ASSERT(NS_IsMainThread()); + if (mOutputStreamManager) { + mOutputStreamManager->Clear(); + } return InvokeAsync(OwnerThread(), this, __func__, &MediaDecoderStateMachine::Shutdown); } diff --git dom/media/mediasink/OutputStreamManager.cpp dom/media/mediasink/OutputStreamManager.cpp index b3ec8936d435e..7ecc203ed8309 100644 --- dom/media/mediasink/OutputStreamManager.cpp +++ dom/media/mediasink/OutputStreamManager.cpp @@ -125,6 +125,13 @@ OutputStreamManager::Remove(MediaStream* aStream) } } +void +OutputStreamManager::Clear() +{ + MOZ_ASSERT(NS_IsMainThread()); + mStreams.Clear(); +} + TrackID OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const { diff --git dom/media/mediasink/OutputStreamManager.h dom/media/mediasink/OutputStreamManager.h index 8e89878e45090..ec5040178ee0b 100644 --- dom/media/mediasink/OutputStreamManager.h +++ dom/media/mediasink/OutputStreamManager.h @@ -59,6 +59,8 @@ public: bool aFinishWhenEnded); // Remove the output stream from the collection. void Remove(MediaStream* aStream); + // Clear all output streams from the collection. + void Clear(); // The next TrackID that will not cause a collision in aOutputStream. TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; // Return true if the collection empty.