Bug 1247189 - part2 : remove reference to TrackBuffersManagers once detached.
Should never access the TrackBuffersManager once the SourceBuffer has been detached.
MozReview-Commit-ID: EgVINj9B1vZ
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -212,16 +212,22 @@ MediaSourceDemuxer::DoDetachSourceBuffer
MonitorAutoLock mon(mMonitor);
if (aSourceBuffer == mAudioTrack) {
mAudioTrack = nullptr;
}
if (aSourceBuffer == mVideoTrack) {
mVideoTrack = nullptr;
}
}
+
+ for (auto& demuxer : mDemuxers) {
+ if (demuxer->HasManager(aSourceBuffer)) {
+ demuxer->DetachManager();
+ }
+ }
ScanSourceBuffersForContent();
}
TrackInfo*
MediaSourceDemuxer::GetTrackInfo(TrackType aTrack)
{
MonitorAutoLock mon(mMonitor);
switch (aTrack) {
@@ -346,16 +352,19 @@ void
MediaSourceTrackDemuxer::Reset()
{
MOZ_ASSERT(mParent, "Called after BreackCycle()");
RefPtr<MediaSourceTrackDemuxer> self = this;
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction("MediaSourceTrackDemuxer::Reset", [self]() {
self->mNextSample.reset();
self->mReset = true;
+ if (!self->mManager) {
+ return;
+ }
self->mManager->Seek(self->mType, TimeUnit::Zero(), TimeUnit::Zero());
{
MonitorAutoLock mon(self->mMonitor);
self->mNextRandomAccessPoint = self->mManager->GetNextRandomAccessPoint(
self->mType, MediaSourceDemuxer::EOS_FUZZ);
}
});
mParent->GetTaskQueue()->Dispatch(task.forget());
@@ -377,34 +386,42 @@ MediaSourceTrackDemuxer::SkipToNextRando
mParent->GetTaskQueue(), this, __func__,
&MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint,
aTimeThreshold);
}
media::TimeIntervals
MediaSourceTrackDemuxer::GetBuffered()
{
+ if (!mManager) {
+ return media::TimeIntervals();
+ }
return mManager->Buffered();
}
void
MediaSourceTrackDemuxer::BreakCycles()
{
RefPtr<MediaSourceTrackDemuxer> self = this;
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction("MediaSourceTrackDemuxer::BreakCycles", [self]() {
self->mParent = nullptr;
- self->mManager = nullptr;
+ self->DetachManager();
});
mParent->GetTaskQueue()->Dispatch(task.forget());
}
RefPtr<MediaSourceTrackDemuxer::SeekPromise>
MediaSourceTrackDemuxer::DoSeek(const TimeUnit& aTime)
{
+ if (!mManager) {
+ return SeekPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("manager is detached.")), __func__);
+ }
TimeIntervals buffered = mManager->Buffered(mType);
// Fuzz factor represents a +/- threshold. So when seeking it allows the gap
// to be twice as big as the fuzz value. We only want to allow EOS_FUZZ gap.
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
TimeUnit seekTime = std::max(aTime - mPreRoll, TimeUnit::Zero());
if (mManager->IsEnded() && seekTime >= buffered.GetEnd()) {
// We're attempting to seek past the end time. Cap seekTime so that we seek
@@ -442,16 +459,21 @@ MediaSourceTrackDemuxer::DoSeek(const Ti
mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
}
return SeekPromise::CreateAndResolve(seekTime, __func__);
}
RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
{
+ if (!mManager) {
+ return SamplesPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("manager is detached.")), __func__);
+ }
if (mReset) {
// If a seek (or reset) was recently performed, we ensure that the data
// we are about to retrieve is still available.
TimeIntervals buffered = mManager->Buffered(mType);
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
if (!buffered.Length() && mManager->IsEnded()) {
return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
@@ -490,16 +512,21 @@ MediaSourceTrackDemuxer::DoGetSamples(in
}
return SamplesPromise::CreateAndResolve(samples, __func__);
}
RefPtr<MediaSourceTrackDemuxer::SkipAccessPointPromise>
MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(
const TimeUnit& aTimeThreadshold)
{
+ if (!mManager) {
+ return SkipAccessPointPromise::CreateAndReject(
+ SkipFailureHolder(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("manager is detached.")), 0), __func__);
+ }
uint32_t parsed = 0;
// Ensure that the data we are about to skip to is still available.
TimeIntervals buffered = mManager->Buffered(mType);
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
if (buffered.ContainsWithStrictEnd(aTimeThreadshold)) {
bool found;
parsed = mManager->SkipToNextRandomAccessPoint(mType,
aTimeThreadshold,
@@ -510,9 +537,21 @@ MediaSourceTrackDemuxer::DoSkipToNextRan
}
}
SkipFailureHolder holder(
mManager->IsEnded() ? NS_ERROR_DOM_MEDIA_END_OF_STREAM :
NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, parsed);
return SkipAccessPointPromise::CreateAndReject(holder, __func__);
}
+bool
+MediaSourceTrackDemuxer::HasManager(TrackBuffersManager* aManager) const
+{
+ return mManager == aManager;
+}
+
+void
+MediaSourceTrackDemuxer::DetachManager()
+{
+ mManager = nullptr;
+}
+
} // namespace mozilla
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -113,16 +113,19 @@ public:
void BreakCycles() override;
bool GetSamplesMayBlock() const override
{
return false;
}
+ bool HasManager(TrackBuffersManager* aManager) const;
+ void DetachManager();
+
private:
RefPtr<SeekPromise> DoSeek(const media::TimeUnit& aTime);
RefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(
const media::TimeUnit& aTimeThreadshold);
already_AddRefed<MediaRawData> GetSample(MediaResult& aError);
// Return the timestamp of the next keyframe after mLastSampleIndex.
media::TimeUnit GetNextRandomAccessPoint();