diff --git a/dom/media/MediaDecoderReader.cpp b/dom/media/MediaDecoderReader.cpp index 5425cfe7a49d..bc6ffcd34b6a 100644 --- a/dom/media/MediaDecoderReader.cpp +++ b/dom/media/MediaDecoderReader.cpp @@ -132,13 +132,15 @@ size_t MediaDecoderReader::SizeOfAudioQueueInFrames() return mAudioQueue.GetSize(); } -nsresult MediaDecoderReader::ResetDecode(TargetQueues aQueues /*= AUDIO_VIDEO*/) +nsresult MediaDecoderReader::ResetDecode(TrackSet aTracks) { - VideoQueue().Reset(); - mVideoDiscontinuity = true; - mBaseVideoPromise.RejectIfExists(CANCELED, __func__); + if (aTracks.contains(TrackInfo::kVideoTrack)) { + VideoQueue().Reset(); + mVideoDiscontinuity = true; + mBaseVideoPromise.RejectIfExists(CANCELED, __func__); + } - if (aQueues == AUDIO_VIDEO) { + if (aTracks.contains(TrackInfo::kAudioTrack)) { AudioQueue().Reset(); mAudioDiscontinuity = true; mBaseAudioPromise.RejectIfExists(CANCELED, __func__); diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index f0c94d5db64d..ed03865576fe 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -6,6 +6,7 @@ #if !defined(MediaDecoderReader_h_) #define MediaDecoderReader_h_ +#include "mozilla/EnumSet.h" #include "mozilla/MozPromise.h" #include "AbstractMediaDecoder.h" @@ -73,10 +74,7 @@ public: CANCELED }; - enum TargetQueues { - VIDEO_ONLY, - AUDIO_VIDEO - }; + using TrackSet = EnumSet; using MetadataPromise = MozPromise, ReadMetadataFailureReason, IsExclusive>; @@ -130,7 +128,11 @@ public: // The first samples of every stream produced after a ResetDecode() call // *must* be marked as "discontinuities". If it's not, seeking work won't // properly! - virtual nsresult ResetDecode(TargetQueues aQueues = AUDIO_VIDEO); + // + // aParam is a set of TrackInfo::TrackType enums specifying which + // queues need to be reset, defaulting to both audio and video tracks. + virtual nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)); // Requests one audio sample from the reader. // diff --git a/dom/media/MediaDecoderReaderWrapper.cpp b/dom/media/MediaDecoderReaderWrapper.cpp index 87f5f2c38bdd..8ee1e3edafd9 100644 --- a/dom/media/MediaDecoderReaderWrapper.cpp +++ b/dom/media/MediaDecoderReaderWrapper.cpp @@ -393,21 +393,24 @@ MediaDecoderReaderWrapper::SetIdle() } void -MediaDecoderReaderWrapper::ResetDecode(TargetQueues aQueues) +MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks) { MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); - if (aQueues == MediaDecoderReader::AUDIO_VIDEO) { + if (aTracks.contains(TrackInfo::kAudioTrack)) { mAudioDataRequest.DisconnectIfExists(); mAudioWaitRequest.DisconnectIfExists(); } - mVideoDataRequest.DisconnectIfExists(); - mVideoWaitRequest.DisconnectIfExists(); + + if (aTracks.contains(TrackInfo::kVideoTrack)) { + mVideoDataRequest.DisconnectIfExists(); + mVideoWaitRequest.DisconnectIfExists(); + } nsCOMPtr r = - NewRunnableMethod(mReader, - &MediaDecoderReader::ResetDecode, - aQueues); + NewRunnableMethod(mReader, + &MediaDecoderReader::ResetDecode, + aTracks); mReader->OwnerThread()->Dispatch(r.forget()); } diff --git a/dom/media/MediaDecoderReaderWrapper.h b/dom/media/MediaDecoderReaderWrapper.h index 91ca51af7e82..2813a19fb600 100644 --- a/dom/media/MediaDecoderReaderWrapper.h +++ b/dom/media/MediaDecoderReaderWrapper.h @@ -32,7 +32,7 @@ class MediaDecoderReaderWrapper { typedef MediaDecoderReader::SeekPromise SeekPromise; typedef MediaDecoderReader::WaitForDataPromise WaitForDataPromise; typedef MediaDecoderReader::BufferedUpdatePromise BufferedUpdatePromise; - typedef MediaDecoderReader::TargetQueues TargetQueues; + typedef MediaDecoderReader::TrackSet TrackSet; NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReaderWrapper); /* @@ -380,7 +380,7 @@ public: void ReleaseMediaResources(); void SetIdle(); - void ResetDecode(TargetQueues aQueues); + void ResetDecode(TrackSet aTracks); nsresult Init() { return mReader->Init(); } bool IsWaitForDataSupported() const { return mReader->IsWaitForDataSupported(); } diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index e3a4496cdd8b..9c3e586fa8f9 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1427,7 +1427,7 @@ void MediaDecoderStateMachine::InitiateVideoDecodeRecoverySeek() // Reset our state machine and decoding pipeline before seeking. if (mSeekTask->NeedToResetMDSM()) { - Reset(MediaDecoderReader::VIDEO_ONLY); + Reset(TrackInfo::kVideoTrack); } // Do the seek. @@ -2395,7 +2395,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine() } void -MediaDecoderStateMachine::Reset(MediaDecoderReader::TargetQueues aQueues /*= AUDIO_VIDEO*/) +MediaDecoderStateMachine::Reset(TrackSet aTracks) { MOZ_ASSERT(OnTaskQueue()); DECODER_LOG("MediaDecoderStateMachine::Reset"); @@ -2408,16 +2408,25 @@ MediaDecoderStateMachine::Reset(MediaDecoderReader::TargetQueues aQueues /*= AUD mState == DECODER_STATE_SEEKING || mState == DECODER_STATE_DORMANT); + // Assert that aTracks specifies to reset the video track because we + // don't currently support resetting just the audio track. + MOZ_ASSERT(aTracks.contains(TrackInfo::kVideoTrack)); - mDecodedVideoEndTime = 0; - mVideoCompleted = false; - VideoQueue().Reset(); - - if (aQueues == MediaDecoderReader::AUDIO_VIDEO) { + if (aTracks.contains(TrackInfo::kAudioTrack) && + aTracks.contains(TrackInfo::kVideoTrack)) { // Stop the audio thread. Otherwise, MediaSink might be accessing AudioQueue // outside of the decoder monitor while we are clearing the queue and causes // crash for no samples to be popped. StopMediaSink(); + } + + if (aTracks.contains(TrackInfo::kVideoTrack)) { + mDecodedVideoEndTime = 0; + mVideoCompleted = false; + VideoQueue().Reset(); + } + + if (aTracks.contains(TrackInfo::kAudioTrack)) { mDecodedAudioEndTime = 0; mAudioCompleted = false; AudioQueue().Reset(); @@ -2428,7 +2437,7 @@ MediaDecoderStateMachine::Reset(MediaDecoderReader::TargetQueues aQueues /*= AUD mPlaybackOffset = 0; - mReader->ResetDecode(aQueues); + mReader->ResetDecode(aTracks); } int64_t diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 72de3134525a..69854e82ae2c 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -135,6 +135,9 @@ enum class MediaEventType : int8_t { class MediaDecoderStateMachine { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderStateMachine) + + using TrackSet = MediaDecoderReader::TrackSet; + public: typedef MediaDecoderOwner::NextFrameStatus NextFrameStatus; typedef mozilla::layers::ImageContainer::FrameID FrameID; @@ -368,7 +371,8 @@ private: // Resets all state related to decoding and playback, emptying all buffers // and aborting all pending operations on the decode task queue. - void Reset(MediaDecoderReader::TargetQueues aQueues = MediaDecoderReader::AUDIO_VIDEO); + void Reset(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)); protected: virtual ~MediaDecoderStateMachine(); diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 39264facaee0..2b8093060fe0 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -1343,7 +1343,7 @@ MediaFormatReader::WaitForData(MediaData::Type aType) } nsresult -MediaFormatReader::ResetDecode(TargetQueues aQueues) +MediaFormatReader::ResetDecode(TrackSet aTracks) { MOZ_ASSERT(OnTaskQueue()); LOGV(""); @@ -1352,15 +1352,22 @@ MediaFormatReader::ResetDecode(TargetQueues aQueues) mSkipRequest.DisconnectIfExists(); // Do the same for any data wait promises. - if (aQueues == AUDIO_VIDEO) { - mAudio.mWaitingPromise.RejectIfExists(WaitForDataRejectValue(MediaData::AUDIO_DATA, WaitForDataRejectValue::CANCELED), __func__); + if (aTracks.contains(TrackInfo::kAudioTrack)) { + mAudio.mWaitingPromise.RejectIfExists( + WaitForDataRejectValue(MediaData::AUDIO_DATA, + WaitForDataRejectValue::CANCELED), __func__); + } + + if (aTracks.contains(TrackInfo::kVideoTrack)) { + mVideo.mWaitingPromise.RejectIfExists( + WaitForDataRejectValue(MediaData::VIDEO_DATA, + WaitForDataRejectValue::CANCELED), __func__); } - mVideo.mWaitingPromise.RejectIfExists(WaitForDataRejectValue(MediaData::VIDEO_DATA, WaitForDataRejectValue::CANCELED), __func__); // Reset miscellaneous seeking state. mPendingSeekTime.reset(); - if (HasVideo()) { + if (HasVideo() && aTracks.contains(TrackInfo::kVideoTrack)) { mVideo.ResetDemuxer(); Reset(TrackInfo::kVideoTrack); if (mVideo.HasPromise()) { @@ -1368,14 +1375,15 @@ MediaFormatReader::ResetDecode(TargetQueues aQueues) } } - if (HasAudio() && aQueues == AUDIO_VIDEO) { + if (HasAudio() && aTracks.contains(TrackInfo::kAudioTrack)) { mAudio.ResetDemuxer(); Reset(TrackInfo::kAudioTrack); if (mAudio.HasPromise()) { mAudio.RejectPromise(CANCELED, __func__); } } - return MediaDecoderReader::ResetDecode(aQueues); + + return MediaDecoderReader::ResetDecode(aTracks); } void diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 9861f067deab..fb49264f0824 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -62,7 +62,7 @@ public: // For Media Resource Management void ReleaseMediaResources() override; - nsresult ResetDecode(TargetQueues aQueues) override; + nsresult ResetDecode(TrackSet aTracks) override; RefPtr Shutdown() override; diff --git a/dom/media/android/AndroidMediaReader.cpp b/dom/media/android/AndroidMediaReader.cpp index 7c9c1aa92a15..59f8441037f7 100644 --- a/dom/media/android/AndroidMediaReader.cpp +++ b/dom/media/android/AndroidMediaReader.cpp @@ -94,7 +94,7 @@ nsresult AndroidMediaReader::ReadMetadata(MediaInfo* aInfo, RefPtr AndroidMediaReader::Shutdown() { - ResetDecode(AUDIO_VIDEO); + ResetDecode(); if (mPlugin) { GetAndroidMediaPluginHost()->DestroyDecoder(mPlugin); mPlugin = nullptr; @@ -104,14 +104,14 @@ AndroidMediaReader::Shutdown() } // Resets all state related to decoding, emptying all buffers etc. -nsresult AndroidMediaReader::ResetDecode(TargetQueues aQueues) +nsresult AndroidMediaReader::ResetDecode(TrackSet aTracks) { if (mLastVideoFrame) { mLastVideoFrame = nullptr; } mSeekRequest.DisconnectIfExists(); mSeekPromise.RejectIfExists(NS_OK, __func__); - return MediaDecoderReader::ResetDecode(aQueues); + return MediaDecoderReader::ResetDecode(aTracks); } bool AndroidMediaReader::DecodeVideoFrame(bool &aKeyframeSkip, diff --git a/dom/media/android/AndroidMediaReader.h b/dom/media/android/AndroidMediaReader.h index 1b5b0c49a37d..195ea869f525 100644 --- a/dom/media/android/AndroidMediaReader.h +++ b/dom/media/android/AndroidMediaReader.h @@ -42,7 +42,8 @@ public: AndroidMediaReader(AbstractMediaDecoder* aDecoder, const nsACString& aContentType); - nsresult ResetDecode(TargetQueues aQueues) override; + nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)) override; bool DecodeAudioData() override; bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) override; diff --git a/dom/media/ogg/OggReader.cpp b/dom/media/ogg/OggReader.cpp index c61bcd009521..8229bbedd9c3 100644 --- a/dom/media/ogg/OggReader.cpp +++ b/dom/media/ogg/OggReader.cpp @@ -169,17 +169,17 @@ nsresult OggReader::Init() { return NS_OK; } -nsresult OggReader::ResetDecode(TargetQueues aQueues) +nsresult OggReader::ResetDecode(TrackSet aTracks) { - return ResetDecode(false, aQueues); + return ResetDecode(false, aTracks); } -nsresult OggReader::ResetDecode(bool start, TargetQueues aQueues) +nsresult OggReader::ResetDecode(bool start, TrackSet aTracks) { MOZ_ASSERT(OnTaskQueue()); nsresult res = NS_OK; - if (NS_FAILED(MediaDecoderReader::ResetDecode(aQueues))) { + if (NS_FAILED(MediaDecoderReader::ResetDecode(aTracks))) { res = NS_ERROR_FAILURE; } diff --git a/dom/media/ogg/OggReader.h b/dom/media/ogg/OggReader.h index 2c5994085421..34e5fa284f4b 100644 --- a/dom/media/ogg/OggReader.h +++ b/dom/media/ogg/OggReader.h @@ -51,7 +51,8 @@ protected: public: nsresult Init() override; - nsresult ResetDecode(TargetQueues aQueues = AUDIO_VIDEO) override; + nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)) override; bool DecodeAudioData() override; // If the Theora granulepos has not been captured, it may read several packets @@ -86,7 +87,9 @@ private: // Specialized Reset() method to signal if the seek is // to the start of the stream. - nsresult ResetDecode(bool start, TargetQueues aQueues = AUDIO_VIDEO); + nsresult ResetDecode(bool start, + TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)); nsresult SeekInternal(int64_t aTime, int64_t aEndTime); diff --git a/dom/media/omx/MediaOmxReader.cpp b/dom/media/omx/MediaOmxReader.cpp index d12f66ca6012..5da68bbdd1d5 100644 --- a/dom/media/omx/MediaOmxReader.cpp +++ b/dom/media/omx/MediaOmxReader.cpp @@ -176,7 +176,7 @@ void MediaOmxReader::ReleaseMediaResources() mMediaResourceRequest.DisconnectIfExists(); mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__); - ResetDecode(AUDIO_VIDEO); + ResetDecode(); // Before freeing a video codec, all video buffers needed to be released // even from graphics pipeline. VideoFrameContainer* container = mDecoder->GetVideoFrameContainer(); diff --git a/dom/media/omx/MediaOmxReader.h b/dom/media/omx/MediaOmxReader.h index 24b195a722e5..c9dfc9adad2d 100644 --- a/dom/media/omx/MediaOmxReader.h +++ b/dom/media/omx/MediaOmxReader.h @@ -74,11 +74,11 @@ protected: void NotifyDataArrivedInternal() override; public: - nsresult ResetDecode(TargetQueues aQueues) override + nsresult ResetDecoder(TrackSet aTracks) override; { mSeekRequest.DisconnectIfExists(); mSeekPromise.RejectIfExists(NS_OK, __func__); - return MediaDecoderReader::ResetDecode(aQueues); + return MediaDecoderReader::ResetDecode(aTracks); } bool DecodeAudioData() override; diff --git a/dom/media/raw/RawReader.cpp b/dom/media/raw/RawReader.cpp index 3b1a0c05276d..b10f5fe287d0 100644 --- a/dom/media/raw/RawReader.cpp +++ b/dom/media/raw/RawReader.cpp @@ -27,10 +27,10 @@ RawReader::~RawReader() MOZ_COUNT_DTOR(RawReader); } -nsresult RawReader::ResetDecode(TargetQueues aQueues) +nsresult RawReader::ResetDecode(TrackSet aTracks) { mCurrentFrame = 0; - return MediaDecoderReader::ResetDecode(aQueues); + return MediaDecoderReader::ResetDecode(aTracks); } nsresult RawReader::ReadMetadata(MediaInfo* aInfo, diff --git a/dom/media/raw/RawReader.h b/dom/media/raw/RawReader.h index 0c7696893cc8..bc3d2eaf67fc 100644 --- a/dom/media/raw/RawReader.h +++ b/dom/media/raw/RawReader.h @@ -20,7 +20,7 @@ protected: ~RawReader(); public: - nsresult ResetDecode(TargetQueues aQueues) override; + nsresult ResetDecode(TrackSet aTracks) override; bool DecodeAudioData() override; bool DecodeVideoFrame(bool &aKeyframeSkip,