Bug 1767899 - Guard some members that expect to be accessed on event target in TrackBuffersManager. r=media-playback-reviewers,alwu

Differential Revision: https://phabricator.services.mozilla.com/D145529
This commit is contained in:
Bryce Seager van Dyk 2022-06-10 18:08:12 +00:00
Родитель e65a048ba9
Коммит 8a8161d85b
2 изменённых файлов: 96 добавлений и 60 удалений

Просмотреть файл

@ -113,7 +113,8 @@ TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
"media.mediasource.eviction_threshold.audio", 20 * 1024 * 1024)), "media.mediasource.eviction_threshold.audio", 20 * 1024 * 1024)),
mEvictionState(EvictionState::NO_EVICTION_NEEDED), mEvictionState(EvictionState::NO_EVICTION_NEEDED),
mMutex("TrackBuffersManager"), mMutex("TrackBuffersManager"),
mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue()) { mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue()),
mTaskQueueCapability(Some(EventTargetCapability{mTaskQueue.get()})) {
MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread"); MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
DDLINKCHILD("parser", mParser.get()); DDLINKCHILD("parser", mParser.get());
} }
@ -193,7 +194,7 @@ void TrackBuffersManager::ProcessTasks() {
return; return;
} }
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
typedef SourceBufferTask::Type Type; typedef SourceBufferTask::Type Type;
if (mCurrentTask) { if (mCurrentTask) {
@ -449,7 +450,7 @@ void TrackBuffersManager::Detach() {
} }
void TrackBuffersManager::CompleteResetParserState() { void TrackBuffersManager::CompleteResetParserState() {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
AUTO_PROFILER_LABEL("TrackBuffersManager::CompleteResetParserState", AUTO_PROFILER_LABEL("TrackBuffersManager::CompleteResetParserState",
MEDIA_PLAYBACK); MEDIA_PLAYBACK);
MSE_DEBUG(""); MSE_DEBUG("");
@ -511,7 +512,7 @@ int64_t TrackBuffersManager::EvictionThreshold() const {
void TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime, void TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime,
int64_t aSizeToEvict) { int64_t aSizeToEvict) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
AUTO_PROFILER_LABEL("TrackBuffersManager::DoEvictData", MEDIA_PLAYBACK); AUTO_PROFILER_LABEL("TrackBuffersManager::DoEvictData", MEDIA_PLAYBACK);
mEvictionState = EvictionState::EVICTION_COMPLETED; mEvictionState = EvictionState::EVICTION_COMPLETED;
@ -612,7 +613,7 @@ void TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime,
RefPtr<TrackBuffersManager::RangeRemovalPromise> RefPtr<TrackBuffersManager::RangeRemovalPromise>
TrackBuffersManager::CodedFrameRemovalWithPromise(TimeInterval aInterval) { TrackBuffersManager::CodedFrameRemovalWithPromise(TimeInterval aInterval) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
RefPtr<RangeRemovalTask> task = new RangeRemovalTask(aInterval); RefPtr<RangeRemovalTask> task = new RangeRemovalTask(aInterval);
RefPtr<RangeRemovalPromise> p = task->mPromise.Ensure(__func__); RefPtr<RangeRemovalPromise> p = task->mPromise.Ensure(__func__);
@ -955,6 +956,7 @@ void TrackBuffersManager::SegmentParserLoop() {
->Then( ->Then(
TaskQueueFromTaskQueue(), __func__, TaskQueueFromTaskQueue(), __func__,
[self](bool aNeedMoreData) { [self](bool aNeedMoreData) {
self->mTaskQueueCapability->AssertOnCurrentThread();
self->mProcessingRequest.Complete(); self->mProcessingRequest.Complete();
if (aNeedMoreData) { if (aNeedMoreData) {
self->NeedMoreData(); self->NeedMoreData();
@ -963,6 +965,7 @@ void TrackBuffersManager::SegmentParserLoop() {
} }
}, },
[self](const MediaResult& aRejectValue) { [self](const MediaResult& aRejectValue) {
self->mTaskQueueCapability->AssertOnCurrentThread();
self->mProcessingRequest.Complete(); self->mProcessingRequest.Complete();
self->RejectAppend(aRejectValue, __func__); self->RejectAppend(aRejectValue, __func__);
}) })
@ -1025,7 +1028,7 @@ void TrackBuffersManager::ShutdownDemuxers() {
} }
void TrackBuffersManager::CreateDemuxerforMIMEType() { void TrackBuffersManager::CreateDemuxerforMIMEType() {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
MSE_DEBUG("mType.OriginalString=%s", mType.OriginalString().get()); MSE_DEBUG("mType.OriginalString=%s", mType.OriginalString().get());
ShutdownDemuxers(); ShutdownDemuxers();
@ -1233,7 +1236,7 @@ bool TrackBuffersManager::IsRepeatInitData(
} }
void TrackBuffersManager::OnDemuxerInitDone(const MediaResult& aResult) { void TrackBuffersManager::OnDemuxerInitDone(const MediaResult& aResult) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
MOZ_DIAGNOSTIC_ASSERT(mInputDemuxer, "mInputDemuxer has been destroyed"); MOZ_DIAGNOSTIC_ASSERT(mInputDemuxer, "mInputDemuxer has been destroyed");
AUTO_PROFILER_LABEL("TrackBuffersManager::OnDemuxerInitDone", MEDIA_PLAYBACK); AUTO_PROFILER_LABEL("TrackBuffersManager::OnDemuxerInitDone", MEDIA_PLAYBACK);
@ -1521,6 +1524,7 @@ void TrackBuffersManager::OnDemuxerInitDone(const MediaResult& aResult) {
} }
void TrackBuffersManager::OnDemuxerInitFailed(const MediaResult& aError) { void TrackBuffersManager::OnDemuxerInitFailed(const MediaResult& aError) {
mTaskQueueCapability->AssertOnCurrentThread();
MSE_DEBUG(""); MSE_DEBUG("");
MOZ_ASSERT(aError != NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA); MOZ_ASSERT(aError != NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
mDemuxerInitRequest.Complete(); mDemuxerInitRequest.Complete();
@ -1619,7 +1623,7 @@ void TrackBuffersManager::MaybeDispatchEncryptedEvent(
void TrackBuffersManager::OnVideoDemuxCompleted( void TrackBuffersManager::OnVideoDemuxCompleted(
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) { RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
MSE_DEBUG("%zu video samples demuxed", aSamples->GetSamples().Length()); MSE_DEBUG("%zu video samples demuxed", aSamples->GetSamples().Length());
mVideoTracks.mDemuxRequest.Complete(); mVideoTracks.mDemuxRequest.Complete();
mVideoTracks.mQueuedSamples.AppendElements(aSamples->GetSamples()); mVideoTracks.mQueuedSamples.AppendElements(aSamples->GetSamples());
@ -1643,7 +1647,7 @@ void TrackBuffersManager::DoDemuxAudio() {
void TrackBuffersManager::OnAudioDemuxCompleted( void TrackBuffersManager::OnAudioDemuxCompleted(
RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) { RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
MSE_DEBUG("%zu audio samples demuxed", aSamples->GetSamples().Length()); MSE_DEBUG("%zu audio samples demuxed", aSamples->GetSamples().Length());
mAudioTracks.mDemuxRequest.Complete(); mAudioTracks.mDemuxRequest.Complete();
mAudioTracks.mQueuedSamples.AppendElements(aSamples->GetSamples()); mAudioTracks.mQueuedSamples.AppendElements(aSamples->GetSamples());
@ -2671,7 +2675,7 @@ TimeUnit TrackBuffersManager::Seek(TrackInfo::TrackType aTrack,
uint32_t TrackBuffersManager::SkipToNextRandomAccessPoint( uint32_t TrackBuffersManager::SkipToNextRandomAccessPoint(
TrackInfo::TrackType aTrack, const TimeUnit& aTimeThreadshold, TrackInfo::TrackType aTrack, const TimeUnit& aTimeThreadshold,
const media::TimeUnit& aFuzz, bool& aFound) { const media::TimeUnit& aFuzz, bool& aFound) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
AUTO_PROFILER_LABEL("TrackBuffersManager::SkipToNextRandomAccessPoint", AUTO_PROFILER_LABEL("TrackBuffersManager::SkipToNextRandomAccessPoint",
MEDIA_PLAYBACK); MEDIA_PLAYBACK);
uint32_t parsed = 0; uint32_t parsed = 0;
@ -2772,7 +2776,7 @@ const MediaRawData* TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
already_AddRefed<MediaRawData> TrackBuffersManager::GetSample( already_AddRefed<MediaRawData> TrackBuffersManager::GetSample(
TrackInfo::TrackType aTrack, const TimeUnit& aFuzz, MediaResult& aResult) { TrackInfo::TrackType aTrack, const TimeUnit& aFuzz, MediaResult& aResult) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
AUTO_PROFILER_LABEL("TrackBuffersManager::GetSample", MEDIA_PLAYBACK); AUTO_PROFILER_LABEL("TrackBuffersManager::GetSample", MEDIA_PLAYBACK);
auto& trackData = GetTracksData(aTrack); auto& trackData = GetTracksData(aTrack);
const TrackBuffer& track = GetTrackBuffer(aTrack); const TrackBuffer& track = GetTrackBuffer(aTrack);
@ -2907,7 +2911,7 @@ uint32_t TrackBuffersManager::Evictable(TrackInfo::TrackType aTrack) const {
TimeUnit TrackBuffersManager::GetNextRandomAccessPoint( TimeUnit TrackBuffersManager::GetNextRandomAccessPoint(
TrackInfo::TrackType aTrack, const TimeUnit& aFuzz) { TrackInfo::TrackType aTrack, const TimeUnit& aFuzz) {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
// So first determine the current position in the track buffer if necessary. // So first determine the current position in the track buffer if necessary.
if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) { if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) {
@ -2938,6 +2942,7 @@ TimeUnit TrackBuffersManager::GetNextRandomAccessPoint(
nsresult TrackBuffersManager::SetNextGetSampleIndexIfNeeded( nsresult TrackBuffersManager::SetNextGetSampleIndexIfNeeded(
TrackInfo::TrackType aTrack, const TimeUnit& aFuzz) { TrackInfo::TrackType aTrack, const TimeUnit& aFuzz) {
MOZ_ASSERT(OnTaskQueue());
auto& trackData = GetTracksData(aTrack); auto& trackData = GetTracksData(aTrack);
const TrackBuffer& track = GetTrackBuffer(aTrack); const TrackBuffer& track = GetTrackBuffer(aTrack);
@ -2997,6 +3002,7 @@ RefPtr<GenericPromise> TrackBuffersManager::RequestDebugInfo(
return RequestDebugInfo(aInfo); return RequestDebugInfo(aInfo);
}); });
} }
mTaskQueueCapability->AssertOnCurrentThread();
GetDebugInfo(aInfo); GetDebugInfo(aInfo);
return GenericPromise::CreateAndResolve(true, __func__); return GenericPromise::CreateAndResolve(true, __func__);
} }
@ -3051,7 +3057,7 @@ void TrackBuffersManager::GetDebugInfo(
void TrackBuffersManager::AddSizeOfResources( void TrackBuffersManager::AddSizeOfResources(
MediaSourceDecoder::ResourceSizes* aSizes) const { MediaSourceDecoder::ResourceSizes* aSizes) const {
MOZ_ASSERT(OnTaskQueue()); mTaskQueueCapability->AssertOnCurrentThread();
if (mInputBuffer.isSome() && mInputBuffer->Buffer()) { if (mInputBuffer.isSome() && mInputBuffer->Buffer()) {
// mInputBuffer should be the sole owner of the underlying buffer, so this // mInputBuffer should be the sole owner of the underlying buffer, so this

Просмотреть файл

@ -8,6 +8,7 @@
#define MOZILLA_TRACKBUFFERSMANAGER_H_ #define MOZILLA_TRACKBUFFERSMANAGER_H_
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/EventTargetCapability.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
@ -152,7 +153,8 @@ class TrackBuffersManager final
const media::TimeUnit& aFuzz, const media::TimeUnit& aFuzz,
MediaResult& aResult); MediaResult& aResult);
int32_t FindCurrentPosition(TrackInfo::TrackType aTrack, int32_t FindCurrentPosition(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz) const; const media::TimeUnit& aFuzz) const
REQUIRES(mTaskQueueCapability);
// Will set the next GetSample index if needed. This information is determined // Will set the next GetSample index if needed. This information is determined
// through the value of mNextSampleTimecode. Return false if the index // through the value of mNextSampleTimecode. Return false if the index
@ -160,7 +162,8 @@ class TrackBuffersManager final
// This occurs if either the track buffer doesn't contain the required // This occurs if either the track buffer doesn't contain the required
// timecode or is empty. // timecode or is empty.
nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack, nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz); const media::TimeUnit& aFuzz)
REQUIRES(mTaskQueueCapability);
media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz); const media::TimeUnit& aFuzz);
@ -180,92 +183,103 @@ class TrackBuffersManager final
// All following functions run on the taskqueue. // All following functions run on the taskqueue.
RefPtr<AppendPromise> DoAppendData(already_AddRefed<MediaByteBuffer> aData, RefPtr<AppendPromise> DoAppendData(already_AddRefed<MediaByteBuffer> aData,
const SourceBufferAttributes& aAttributes); const SourceBufferAttributes& aAttributes);
void ScheduleSegmentParserLoop(); void ScheduleSegmentParserLoop() REQUIRES(mTaskQueueCapability);
void SegmentParserLoop(); void SegmentParserLoop() REQUIRES(mTaskQueueCapability);
void InitializationSegmentReceived(); void InitializationSegmentReceived() REQUIRES(mTaskQueueCapability);
void ShutdownDemuxers(); void ShutdownDemuxers() REQUIRES(mTaskQueueCapability);
void CreateDemuxerforMIMEType(); void CreateDemuxerforMIMEType() REQUIRES(mTaskQueueCapability);
void ResetDemuxingState(); void ResetDemuxingState() REQUIRES(mTaskQueueCapability);
void NeedMoreData(); void NeedMoreData() REQUIRES(mTaskQueueCapability);
void RejectAppend(const MediaResult& aRejectValue, const char* aName); void RejectAppend(const MediaResult& aRejectValue, const char* aName)
REQUIRES(mTaskQueueCapability);
// Will return a promise that will be resolved once all frames of the current // Will return a promise that will be resolved once all frames of the current
// media segment have been processed. // media segment have been processed.
RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing(); RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing()
void CompleteCodedFrameProcessing(); REQUIRES(mTaskQueueCapability);
void CompleteCodedFrameProcessing() REQUIRES(mTaskQueueCapability);
// Called by ResetParserState. // Called by ResetParserState.
void CompleteResetParserState(); void CompleteResetParserState() REQUIRES(mTaskQueueCapability);
RefPtr<RangeRemovalPromise> CodedFrameRemovalWithPromise( RefPtr<RangeRemovalPromise> CodedFrameRemovalWithPromise(
media::TimeInterval aInterval); media::TimeInterval aInterval) REQUIRES(mTaskQueueCapability);
bool CodedFrameRemoval(media::TimeInterval aInterval); bool CodedFrameRemoval(media::TimeInterval aInterval)
REQUIRES(mTaskQueueCapability);
// Removes all coded frames -- this is not to spec and should be used as a // Removes all coded frames -- this is not to spec and should be used as a
// last resort to clear buffers only if other methods cannot. // last resort to clear buffers only if other methods cannot.
void RemoveAllCodedFrames(); void RemoveAllCodedFrames() REQUIRES(mTaskQueueCapability);
void SetAppendState(SourceBufferAttributes::AppendState aAppendState); void SetAppendState(SourceBufferAttributes::AppendState aAppendState)
REQUIRES(mTaskQueueCapability);
bool HasVideo() const { return mVideoTracks.mNumTracks > 0; } bool HasVideo() const { return mVideoTracks.mNumTracks > 0; }
bool HasAudio() const { return mAudioTracks.mNumTracks > 0; } bool HasAudio() const { return mAudioTracks.mNumTracks > 0; }
// The input buffer as per // The input buffer as per
// http://w3c.github.io/media-source/index.html#sourcebuffer-input-buffer // http://w3c.github.io/media-source/index.html#sourcebuffer-input-buffer
Maybe<MediaSpan> mInputBuffer; Maybe<MediaSpan> mInputBuffer GUARDED_BY(mTaskQueueCapability);
// Buffer full flag as per // Buffer full flag as per
// https://w3c.github.io/media-source/#sourcebuffer-buffer-full-flag. Accessed // https://w3c.github.io/media-source/#sourcebuffer-buffer-full-flag. Accessed
// on both the main thread and the task queue. // on both the main thread and the task queue.
Atomic<bool> mBufferFull; Atomic<bool> mBufferFull;
bool mFirstInitializationSegmentReceived; bool mFirstInitializationSegmentReceived GUARDED_BY(mTaskQueueCapability);
bool mChangeTypeReceived; bool mChangeTypeReceived GUARDED_BY(mTaskQueueCapability);
// Set to true once a new segment is started. // Set to true once a new segment is started.
bool mNewMediaSegmentStarted; bool mNewMediaSegmentStarted GUARDED_BY(mTaskQueueCapability);
bool mActiveTrack; bool mActiveTrack GUARDED_BY(mTaskQueueCapability);
MediaContainerType mType; MediaContainerType mType GUARDED_BY(mTaskQueueCapability);
// ContainerParser objects and methods. // ContainerParser objects and methods.
// Those are used to parse the incoming input buffer. // Those are used to parse the incoming input buffer.
// Recreate the ContainerParser and if aReuseInitData is true then // Recreate the ContainerParser and if aReuseInitData is true then
// feed it with the previous init segment found. // feed it with the previous init segment found.
void RecreateParser(bool aReuseInitData); void RecreateParser(bool aReuseInitData) REQUIRES(mTaskQueueCapability);
UniquePtr<ContainerParser> mParser; UniquePtr<ContainerParser> mParser;
// Demuxer objects and methods. // Demuxer objects and methods.
void AppendDataToCurrentInputBuffer(const MediaSpan& aData); void AppendDataToCurrentInputBuffer(const MediaSpan& aData)
REQUIRES(mTaskQueueCapability);
RefPtr<MediaByteBuffer> mInitData; RefPtr<MediaByteBuffer> mInitData GUARDED_BY(mTaskQueueCapability);
// Checks if a new set of init data is a repeat of the last set of init data // Checks if a new set of init data is a repeat of the last set of init data
// received. Because streams may retransmit the same init data (or // received. Because streams may retransmit the same init data (or
// functionally equivalent init data) we do not want to perform costly // functionally equivalent init data) we do not want to perform costly
// operations each time we receive init data, only when it's actually // operations each time we receive init data, only when it's actually
// different data. // different data.
bool IsRepeatInitData(const MediaInfo& aNewMediaInfo) const; bool IsRepeatInitData(const MediaInfo& aNewMediaInfo) const
REQUIRES(mTaskQueueCapability);
// Temporary input buffer to handle partial media segment header. // Temporary input buffer to handle partial media segment header.
// We store the current input buffer content into it should we need to // We store the current input buffer content into it should we need to
// reinitialize the demuxer once we have some samples and a discontinuity is // reinitialize the demuxer once we have some samples and a discontinuity is
// detected. // detected.
Maybe<MediaSpan> mPendingInputBuffer; Maybe<MediaSpan> mPendingInputBuffer GUARDED_BY(mTaskQueueCapability);
RefPtr<SourceBufferResource> mCurrentInputBuffer; RefPtr<SourceBufferResource> mCurrentInputBuffer
RefPtr<MediaDataDemuxer> mInputDemuxer; GUARDED_BY(mTaskQueueCapability);
RefPtr<MediaDataDemuxer> mInputDemuxer GUARDED_BY(mTaskQueueCapability);
// Length already processed in current media segment. // Length already processed in current media segment.
uint64_t mProcessedInput; uint64_t mProcessedInput GUARDED_BY(mTaskQueueCapability);
Maybe<media::TimeUnit> mLastParsedEndTime; Maybe<media::TimeUnit> mLastParsedEndTime GUARDED_BY(mTaskQueueCapability);
void OnDemuxerInitDone(const MediaResult& aResult); void OnDemuxerInitDone(const MediaResult& aResult);
void OnDemuxerInitFailed(const MediaResult& aFailure); void OnDemuxerInitFailed(const MediaResult& aFailure);
void OnDemuxerResetDone(const MediaResult& aResult); void OnDemuxerResetDone(const MediaResult& aResult)
REQUIRES(mTaskQueueCapability);
MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest; MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
void OnDemuxFailed(TrackType aTrack, const MediaResult& aError); void OnDemuxFailed(TrackType aTrack, const MediaResult& aError)
void DoDemuxVideo(); REQUIRES(mTaskQueueCapability);
void DoDemuxVideo() REQUIRES(mTaskQueueCapability);
void OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples); void OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
void OnVideoDemuxFailed(const MediaResult& aError) { void OnVideoDemuxFailed(const MediaResult& aError) {
mVideoTracks.mDemuxRequest.Complete(); mVideoTracks.mDemuxRequest.Complete();
mTaskQueueCapability->AssertOnCurrentThread();
OnDemuxFailed(TrackType::kVideoTrack, aError); OnDemuxFailed(TrackType::kVideoTrack, aError);
} }
void DoDemuxAudio(); void DoDemuxAudio() REQUIRES(mTaskQueueCapability);
void OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples); void OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
void OnAudioDemuxFailed(const MediaResult& aError) { void OnAudioDemuxFailed(const MediaResult& aError) {
mAudioTracks.mDemuxRequest.Complete(); mAudioTracks.mDemuxRequest.Complete();
mTaskQueueCapability->AssertOnCurrentThread();
OnDemuxFailed(TrackType::kAudioTrack, aError); OnDemuxFailed(TrackType::kAudioTrack, aError);
} }
@ -274,9 +288,11 @@ class TrackBuffersManager final
void MaybeDispatchEncryptedEvent( void MaybeDispatchEncryptedEvent(
const nsTArray<RefPtr<MediaRawData>>& aSamples); const nsTArray<RefPtr<MediaRawData>>& aSamples);
void DoEvictData(const media::TimeUnit& aPlaybackTime, int64_t aSizeToEvict); void DoEvictData(const media::TimeUnit& aPlaybackTime, int64_t aSizeToEvict)
REQUIRES(mTaskQueueCapability);
void GetDebugInfo(dom::TrackBuffersManagerDebugInfo& aInfo) const; void GetDebugInfo(dom::TrackBuffersManagerDebugInfo& aInfo) const
REQUIRES(mTaskQueueCapability);
struct TrackData { struct TrackData {
TrackData() : mNumTracks(0), mNeedRandomAccessPoint(true), mSizeBuffer(0) {} TrackData() : mNumTracks(0), mNeedRandomAccessPoint(true), mSizeBuffer(0) {}
@ -399,16 +415,21 @@ class TrackBuffersManager final
void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const; void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;
}; };
void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime); void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime)
void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData); REQUIRES(mTaskQueueCapability);
media::TimeInterval PresentationInterval(const TrackBuffer& aSamples) const; void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData)
REQUIRES(mTaskQueueCapability);
media::TimeInterval PresentationInterval(const TrackBuffer& aSamples) const
REQUIRES(mTaskQueueCapability);
bool CheckNextInsertionIndex(TrackData& aTrackData, bool CheckNextInsertionIndex(TrackData& aTrackData,
const media::TimeUnit& aSampleTime); const media::TimeUnit& aSampleTime)
REQUIRES(mTaskQueueCapability);
void InsertFrames(TrackBuffer& aSamples, void InsertFrames(TrackBuffer& aSamples,
const media::TimeIntervals& aIntervals, const media::TimeIntervals& aIntervals,
TrackData& aTrackData); TrackData& aTrackData) REQUIRES(mTaskQueueCapability);
void UpdateHighestTimestamp(TrackData& aTrackData, void UpdateHighestTimestamp(TrackData& aTrackData,
const media::TimeUnit& aHighestTime); const media::TimeUnit& aHighestTime)
REQUIRES(mTaskQueueCapability);
// Remove all frames and their dependencies contained in aIntervals. // Remove all frames and their dependencies contained in aIntervals.
// Return the index at which frames were first removed or 0 if no frames // Return the index at which frames were first removed or 0 if no frames
// removed. // removed.
@ -486,14 +507,15 @@ class TrackBuffersManager final
void ProcessTasks(); void ProcessTasks();
// Set if the TrackBuffersManager is currently processing a task. // Set if the TrackBuffersManager is currently processing a task.
// At this stage, this task is always a AppendBufferTask. // At this stage, this task is always a AppendBufferTask.
RefPtr<SourceBufferTask> mCurrentTask; RefPtr<SourceBufferTask> mCurrentTask GUARDED_BY(mTaskQueueCapability);
// Current SourceBuffer state for ongoing task. // Current SourceBuffer state for ongoing task.
// Its content is returned to the SourceBuffer once the AppendBufferTask has // Its content is returned to the SourceBuffer once the AppendBufferTask has
// completed. // completed.
UniquePtr<SourceBufferAttributes> mSourceBufferAttributes; UniquePtr<SourceBufferAttributes> mSourceBufferAttributes
GUARDED_BY(mTaskQueueCapability);
// The current sourcebuffer append window. It's content is equivalent to // The current sourcebuffer append window. It's content is equivalent to
// mSourceBufferAttributes.mAppendWindowStart/End // mSourceBufferAttributes.mAppendWindowStart/End
media::TimeInterval mAppendWindow; media::TimeInterval mAppendWindow GUARDED_BY(mTaskQueueCapability);
// Strong references to external objects. // Strong references to external objects.
nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder; nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;
@ -530,6 +552,14 @@ class TrackBuffersManager final
media::TimeIntervals mAudioBufferedRanges; media::TimeIntervals mAudioBufferedRanges;
// MediaInfo of the first init segment read. // MediaInfo of the first init segment read.
MediaInfo mInfo; MediaInfo mInfo;
// End mutex protected members.
// EventTargetCapability used to ensure we're running on the task queue
// as expected for various accesses.
// TODO: we could store only this and dispatch to it, rather than also having
// mTaskQueue. However, there's special locking around mTaskQueue, so we keep
// both for now.
Maybe<EventTargetCapability<TaskQueue>> mTaskQueueCapability;
}; };
} // namespace mozilla } // namespace mozilla