Skip to content

Commit 0bdecfc

Browse files
wolfbeastroytam1
wolfbeast
authored andcommitted
Media: harden TrackID handling.
1 parent bfe6f25 commit 0bdecfc

9 files changed

+183
-37
lines changed

dom/html/HTMLMediaElement.cpp

+42-5
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
817817
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError)
818818
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
819819
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
820+
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mPreCreatedTracks);
820821
}
821822
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
822823
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
@@ -1020,6 +1021,17 @@ void HTMLMediaElement::ShutdownDecoder()
10201021
RemoveMediaElementFromURITable();
10211022
NS_ASSERTION(mDecoder, "Must have decoder to shut down");
10221023
mWaitingForKeyListener.DisconnectIfExists();
1024+
for (OutputMediaStream& out : mOutputStreams) {
1025+
if (!out.mCapturingDecoder) {
1026+
continue;
1027+
}
1028+
if (!out.mStream) {
1029+
continue;
1030+
}
1031+
out.mNextAvailableTrackID = std::max<TrackID>(
1032+
mDecoder->NextAvailableTrackIDFor(out.mStream->GetInputStream()),
1033+
out.mNextAvailableTrackID);
1034+
}
10231035
mDecoder->Shutdown();
10241036
mDecoder = nullptr;
10251037
}
@@ -2730,6 +2742,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
27302742
if (mDecoder) {
27312743
out->mCapturingDecoder = true;
27322744
mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
2745+
out->mNextAvailableTrackID,
27332746
aFinishWhenEnded);
27342747
} else if (mSrcStream) {
27352748
out->mCapturingMediaStream = true;
@@ -2743,23 +2756,26 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
27432756

27442757
if (mDecoder) {
27452758
if (HasAudio()) {
2746-
TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
2759+
TrackID audioTrackId = out->mNextAvailableTrackID++;
27472760
RefPtr<MediaStreamTrackSource> trackSource =
27482761
getter->GetMediaStreamTrackSource(audioTrackId);
27492762
RefPtr<MediaStreamTrack> track =
2750-
out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO,
2763+
out->mStream->CreateDOMTrack(audioTrackId,
2764+
MediaSegment::AUDIO,
27512765
trackSource);
2766+
out->mPreCreatedTracks.AppendElement(track);
27522767
out->mStream->AddTrackInternal(track);
27532768
LOG(LogLevel::Debug,
27542769
("Created audio track %d for captured decoder", audioTrackId));
27552770
}
27562771
if (IsVideo() && HasVideo() && !out->mCapturingAudioOnly) {
2757-
TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
2772+
TrackID videoTrackId = out->mNextAvailableTrackID++;
27582773
RefPtr<MediaStreamTrackSource> trackSource =
27592774
getter->GetMediaStreamTrackSource(videoTrackId);
27602775
RefPtr<MediaStreamTrack> track =
27612776
out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
27622777
trackSource);
2778+
out->mPreCreatedTracks.AppendElement(track);
27632779
out->mStream->AddTrackInternal(track);
27642780
LOG(LogLevel::Debug,
27652781
("Created video track %d for captured decoder", videoTrackId));
@@ -2848,6 +2864,25 @@ NS_IMETHODIMP HTMLMediaElement::GetMozAudioCaptured(bool* aCaptured)
28482864
return NS_OK;
28492865
}
28502866

2867+
void
2868+
HTMLMediaElement::EndPreCreatedCapturedDecoderTracks()
2869+
{
2870+
MOZ_ASSERT(NS_IsMainThread());
2871+
for (OutputMediaStream& ms : mOutputStreams) {
2872+
if (!ms.mCapturingDecoder) {
2873+
continue;
2874+
}
2875+
for (RefPtr<MediaStreamTrack>& t : ms.mPreCreatedTracks) {
2876+
if (t->Ended()) {
2877+
continue;
2878+
}
2879+
NS_DispatchToMainThread(NewRunnableMethod(
2880+
t, &MediaStreamTrack::OverrideEnded));
2881+
}
2882+
ms.mPreCreatedTracks.Clear();
2883+
}
2884+
}
2885+
28512886
class MediaElementSetForURI : public nsURIHashKey {
28522887
public:
28532888
explicit MediaElementSetForURI(const nsIURI* aKey) : nsURIHashKey(aKey) {}
@@ -3380,11 +3415,12 @@ HTMLMediaElement::WakeLockRelease()
33803415
}
33813416

33823417
HTMLMediaElement::OutputMediaStream::OutputMediaStream()
3383-
: mFinishWhenEnded(false)
3418+
: mNextAvailableTrackID(1)
3419+
, mFinishWhenEnded(false)
33843420
, mCapturingAudioOnly(false)
33853421
, mCapturingDecoder(false)
33863422
, mCapturingMediaStream(false)
3387-
, mNextAvailableTrackID(1) {}
3423+
{}
33883424

33893425
HTMLMediaElement::OutputMediaStream::~OutputMediaStream()
33903426
{
@@ -4008,6 +4044,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
40084044

40094045
ms.mCapturingDecoder = true;
40104046
aDecoder->AddOutputStream(ms.mStream->GetInputStream()->AsProcessedStream(),
4047+
ms.mNextAvailableTrackID,
40114048
ms.mFinishWhenEnded);
40124049
}
40134050

dom/html/HTMLMediaElement.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,11 @@ class HTMLMediaElement : public nsGenericHTMLElement,
675675
return mAudioCaptured;
676676
}
677677

678+
/**
679+
* Ensures any MediaStreamTracks captured from a MediaDecoder are ended.
680+
*/
681+
void EndPreCreatedCapturedDecoderTracks();
682+
678683
void MozGetMetadata(JSContext* aCx, JS::MutableHandle<JSObject*> aResult,
679684
ErrorResult& aRv);
680685

@@ -815,13 +820,18 @@ class HTMLMediaElement : public nsGenericHTMLElement,
815820
~OutputMediaStream();
816821

817822
RefPtr<DOMMediaStream> mStream;
823+
TrackID mNextAvailableTrackID;
818824
bool mFinishWhenEnded;
819825
bool mCapturingAudioOnly;
820826
bool mCapturingDecoder;
821827
bool mCapturingMediaStream;
822828

829+
// The following members are keeping state for a captured MediaDecoder.
830+
// Tracks that were created on main thread before MediaDecoder fed them
831+
// to the MediaStreamGraph.
832+
nsTArray<RefPtr<MediaStreamTrack>> mPreCreatedTracks;
833+
823834
// The following members are keeping state for a captured MediaStream.
824-
TrackID mNextAvailableTrackID;
825835
nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts;
826836
};
827837

dom/media/MediaDecoder.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,13 @@ MediaDecoder::SetVolume(double aVolume)
327327

328328
void
329329
MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream,
330+
TrackID aNextAvailableTrackID,
330331
bool aFinishWhenEnded)
331332
{
332333
MOZ_ASSERT(NS_IsMainThread());
333334
MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
334-
mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded);
335+
mDecoderStateMachine->AddOutputStream(
336+
aStream, aNextAvailableTrackID, aFinishWhenEnded);
335337
}
336338

337339
void
@@ -342,6 +344,14 @@ MediaDecoder::RemoveOutputStream(MediaStream* aStream)
342344
mDecoderStateMachine->RemoveOutputStream(aStream);
343345
}
344346

347+
TrackID
348+
MediaDecoder::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
349+
{
350+
MOZ_ASSERT(NS_IsMainThread());
351+
MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
352+
return mDecoderStateMachine->NextAvailableTrackIDFor(aOutputStream);
353+
}
354+
345355
double
346356
MediaDecoder::GetDuration()
347357
{
@@ -1736,6 +1746,8 @@ MediaDecoder::RemoveMediaTracks()
17361746
videoList->RemoveTracks();
17371747
}
17381748

1749+
element->EndPreCreatedCapturedDecoderTracks();
1750+
17391751
mMediaTracksConstructed = false;
17401752
}
17411753

dom/media/MediaDecoder.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,13 @@ class MediaDecoder : public AbstractMediaDecoder
210210
// Add an output stream. All decoder output will be sent to the stream.
211211
// The stream is initially blocked. The decoder is responsible for unblocking
212212
// it while it is playing back.
213-
virtual void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
213+
virtual void AddOutputStream(ProcessedMediaStream* aStream,
214+
TrackID aNextAvailableTrackID,
215+
bool aFinishWhenEnded);
214216
// Remove an output stream added with AddOutputStream.
215217
virtual void RemoveOutputStream(MediaStream* aStream);
218+
// The next TrackID that can be used without risk of a collision.
219+
virtual TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
216220

217221
// Return the duration of the video in seconds.
218222
virtual double GetDuration();

dom/media/MediaDecoderStateMachine.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -2835,6 +2835,10 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
28352835
RefPtr<ShutdownPromise>
28362836
MediaDecoderStateMachine::BeginShutdown()
28372837
{
2838+
MOZ_ASSERT(NS_IsMainThread());
2839+
if (mOutputStreamManager) {
2840+
mOutputStreamManager->Clear();
2841+
}
28382842
return InvokeAsync(OwnerThread(), this, __func__,
28392843
&MediaDecoderStateMachine::Shutdown);
28402844
}
@@ -3250,11 +3254,12 @@ MediaDecoderStateMachine::DumpDebugInfo()
32503254
}
32513255

32523256
void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
3257+
TrackID aNextAvailableTrackID,
32533258
bool aFinishWhenEnded)
32543259
{
32553260
MOZ_ASSERT(NS_IsMainThread());
32563261
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
3257-
mOutputStreamManager->Add(aStream, aFinishWhenEnded);
3262+
mOutputStreamManager->Add(aStream, aNextAvailableTrackID, aFinishWhenEnded);
32583263
nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
32593264
this, &MediaDecoderStateMachine::SetAudioCaptured, true);
32603265
OwnerThread()->Dispatch(r.forget());
@@ -3269,9 +3274,17 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
32693274
nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
32703275
this, &MediaDecoderStateMachine::SetAudioCaptured, false);
32713276
OwnerThread()->Dispatch(r.forget());
3277+
32723278
}
32733279
}
32743280

3281+
TrackID
3282+
MediaDecoderStateMachine::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
3283+
{
3284+
MOZ_ASSERT(NS_IsMainThread());
3285+
return mOutputStreamManager->NextAvailableTrackIDFor(aOutputStream);
3286+
}
3287+
32753288
size_t
32763289
MediaDecoderStateMachine::SizeOfVideoQueue() const
32773290
{

dom/media/MediaDecoderStateMachine.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,12 @@ class MediaDecoderStateMachine
168168

169169
void DumpDebugInfo();
170170

171-
void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
171+
void AddOutputStream(ProcessedMediaStream* aStream,
172+
TrackID aNextAvailableTrackID,
173+
bool aFinishWhenEnded);
172174
// Remove an output stream added with AddOutputStream.
173175
void RemoveOutputStream(MediaStream* aStream);
176+
TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const;
174177

175178
// Seeks to the decoder to aTarget asynchronously.
176179
RefPtr<MediaDecoder::SeekPromise> InvokeSeek(SeekTarget aTarget);

dom/media/mediasink/DecodedStream.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,22 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
181181
, mOutputStreamManager(aOutputStreamManager)
182182
{
183183
mStream->AddListener(mListener);
184-
mOutputStreamManager->Connect(mStream);
184+
TrackID audioTrack = TRACK_NONE;
185+
TrackID videoTrack = TRACK_NONE;
185186

186187
// Initialize tracks.
187188
if (aInit.mInfo.HasAudio()) {
188-
mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId,
189+
audioTrack = aInit.mInfo.mAudio.mTrackId;
190+
mStream->AddAudioTrack(audioTrack,
189191
aInit.mInfo.mAudio.mRate,
190192
0, new AudioSegment());
191193
}
192194
if (aInit.mInfo.HasVideo()) {
193-
mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment());
195+
videoTrack = aInit.mInfo.mVideo.mTrackId;
196+
mStream->AddTrack(videoTrack, 0, new VideoSegment());
194197
}
198+
199+
mOutputStreamManager->Connect(mStream, audioTrack, videoTrack);
195200
}
196201

197202
DecodedStreamData::~DecodedStreamData()

0 commit comments

Comments
 (0)