MediaDecoderStateMachineBase.cpp (7775B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "MediaDecoderStateMachineBase.h" 6 7 #include "MediaDecoder.h" 8 #include "mozilla/ProfilerMarkers.h" 9 #include "mozilla/TaskQueue.h" 10 #include "nsThreadUtils.h" 11 12 namespace mozilla { 13 14 #define INIT_MIRROR(name, val) \ 15 name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Mirror)") 16 #define INIT_CANONICAL(name, val) \ 17 name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Canonical)") 18 #define FMT(x, ...) "Decoder=%p " x, mDecoderID, ##__VA_ARGS__ 19 #define LOG(x, ...) \ 20 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, "Decoder=%p " x, mDecoderID, \ 21 ##__VA_ARGS__) 22 #define LOGV(x, ...) \ 23 DDMOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, "Decoder=%p " x, mDecoderID, \ 24 ##__VA_ARGS__) 25 #define LOGW(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get()) 26 #define LOGE(x, ...) \ 27 NS_DebugBreak(NS_DEBUG_WARNING, \ 28 nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, \ 29 __FILE__, __LINE__) 30 31 MediaDecoderStateMachineBase::MediaDecoderStateMachineBase( 32 MediaDecoder* aDecoder, MediaFormatReader* aReader) 33 : mDecoderID(aDecoder), 34 mAbstractMainThread(aDecoder->AbstractMainThread()), 35 mFrameStats(&aDecoder->GetFrameStatistics()), 36 mVideoFrameContainer(aDecoder->GetVideoFrameContainer()), 37 mTaskQueue(TaskQueue::Create(GetMediaThreadPool(MediaThreadType::MDSM), 38 "MDSM::mTaskQueue", 39 /* aSupportsTailDispatch = */ true)), 40 mReader(new ReaderProxy(mTaskQueue, aReader)), 41 mPlaybackRate(1.0), 42 INIT_MIRROR(mBuffered, media::TimeIntervals()), 43 INIT_MIRROR(mPlayState, MediaDecoder::PLAY_STATE_LOADING), 44 INIT_MIRROR(mVolume, 1.0), 45 INIT_MIRROR(mPreservesPitch, true), 46 INIT_MIRROR(mLooping, false), 47 INIT_MIRROR(mSecondaryVideoContainer, nullptr), 48 INIT_CANONICAL(mDuration, media::NullableTimeUnit()), 49 INIT_CANONICAL(mCurrentPosition, media::TimeUnit::Zero()), 50 INIT_CANONICAL(mIsAudioDataAudible, false), 51 mMinimizePreroll(aDecoder->GetMinimizePreroll()), 52 mIsLiveStream(false), 53 mWatchManager(this, mTaskQueue) {} 54 55 MediaEventSource<void>& MediaDecoderStateMachineBase::OnMediaNotSeekable() 56 const { 57 return mReader->OnMediaNotSeekable(); 58 } 59 60 AbstractCanonical<media::TimeIntervals>* 61 MediaDecoderStateMachineBase::CanonicalBuffered() const { 62 return mReader->CanonicalBuffered(); 63 } 64 65 void MediaDecoderStateMachineBase::DispatchSetFragmentEndTime( 66 const media::TimeUnit& aEndTime) { 67 OwnerThread()->DispatchStateChange(NewRunnableMethod<media::TimeUnit>( 68 "MediaDecoderStateMachineBase::SetFragmentEndTime", this, 69 &MediaDecoderStateMachineBase::SetFragmentEndTime, aEndTime)); 70 } 71 72 void MediaDecoderStateMachineBase::DispatchCanPlayThrough( 73 bool aCanPlayThrough) { 74 OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>( 75 "MediaDecoderStateMachineBase::SetCanPlayThrough", this, 76 &MediaDecoderStateMachineBase::SetCanPlayThrough, aCanPlayThrough)); 77 } 78 79 void MediaDecoderStateMachineBase::DispatchIsLiveStream(bool aIsLiveStream) { 80 OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>( 81 "MediaDecoderStateMachineBase::SetIsLiveStream", this, 82 &MediaDecoderStateMachineBase::SetIsLiveStream, aIsLiveStream)); 83 } 84 85 void MediaDecoderStateMachineBase::DispatchSetPlaybackRate( 86 double aPlaybackRate) { 87 OwnerThread()->DispatchStateChange(NewRunnableMethod<double>( 88 "MediaDecoderStateMachineBase::SetPlaybackRate", this, 89 &MediaDecoderStateMachineBase::SetPlaybackRate, aPlaybackRate)); 90 } 91 92 nsresult MediaDecoderStateMachineBase::Init(MediaDecoder* aDecoder) { 93 MOZ_ASSERT(NS_IsMainThread()); 94 95 // Dispatch initialization that needs to happen on that task queue. 96 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<RefPtr<MediaDecoder>>( 97 "MediaDecoderStateMachineBase::InitializationTask", this, 98 &MediaDecoderStateMachineBase::InitializationTask, aDecoder); 99 mTaskQueue->DispatchStateChange(r.forget()); 100 101 // Connect mirrors. 102 aDecoder->CanonicalPlayState().ConnectMirror(&mPlayState); 103 aDecoder->CanonicalVolume().ConnectMirror(&mVolume); 104 aDecoder->CanonicalPreservesPitch().ConnectMirror(&mPreservesPitch); 105 aDecoder->CanonicalLooping().ConnectMirror(&mLooping); 106 aDecoder->CanonicalSecondaryVideoContainer().ConnectMirror( 107 &mSecondaryVideoContainer); 108 109 nsresult rv = mReader->Init(); 110 NS_ENSURE_SUCCESS(rv, rv); 111 112 mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread()); 113 114 return NS_OK; 115 } 116 117 void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder* aDecoder) { 118 MOZ_ASSERT(OnTaskQueue()); 119 120 // Connect mirrors. 121 mBuffered.Connect(mReader->CanonicalBuffered()); 122 mReader->SetCanonicalDuration(mDuration); 123 124 // Initialize watchers. 125 mWatchManager.Watch(mBuffered, 126 &MediaDecoderStateMachineBase::BufferedRangeUpdated); 127 mWatchManager.Watch(mVolume, &MediaDecoderStateMachineBase::VolumeChanged); 128 mWatchManager.Watch(mPreservesPitch, 129 &MediaDecoderStateMachineBase::PreservesPitchChanged); 130 mWatchManager.Watch(mPlayState, 131 &MediaDecoderStateMachineBase::PlayStateChanged); 132 mWatchManager.Watch(mLooping, &MediaDecoderStateMachineBase::LoopingChanged); 133 mWatchManager.Watch( 134 mSecondaryVideoContainer, 135 &MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer); 136 } 137 138 RefPtr<ShutdownPromise> MediaDecoderStateMachineBase::BeginShutdown() { 139 MOZ_ASSERT(NS_IsMainThread()); 140 return InvokeAsync( 141 OwnerThread(), __func__, 142 [self = RefPtr<MediaDecoderStateMachineBase>(this), this]() { 143 mWatchManager.Shutdown(); 144 mBuffered.DisconnectIfConnected(); 145 mPlayState.DisconnectIfConnected(); 146 mVolume.DisconnectIfConnected(); 147 mPreservesPitch.DisconnectIfConnected(); 148 mLooping.DisconnectIfConnected(); 149 mSecondaryVideoContainer.DisconnectIfConnected(); 150 return Shutdown(); 151 }); 152 } 153 154 RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachineBase::InvokeSeek( 155 const SeekTarget& aTarget) { 156 return InvokeAsync(OwnerThread(), __func__, 157 [self = RefPtr<MediaDecoderStateMachineBase>(this), 158 target = aTarget]() { return self->Seek(target); }); 159 } 160 161 bool MediaDecoderStateMachineBase::OnTaskQueue() const { 162 return OwnerThread()->IsCurrentThreadIn(); 163 } 164 165 void MediaDecoderStateMachineBase::DecodeError(const MediaResult& aError) { 166 MOZ_ASSERT(OnTaskQueue()); 167 if (aError != NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR) { 168 LOGE("Decode error: %s", aError.Description().get()); 169 } 170 PROFILER_MARKER_TEXT("MDSMBase::DecodeError", MEDIA_PLAYBACK, {}, 171 aError.Description()); 172 // Notify the decode error and MediaDecoder will shut down MDSM. 173 mOnPlaybackErrorEvent.Notify(aError); 174 #ifdef DEBUG 175 mHasNotifiedPlaybackError = true; 176 #endif 177 } 178 179 RefPtr<SetCDMPromise> MediaDecoderStateMachineBase::SetCDMProxy( 180 CDMProxy* aProxy) { 181 return mReader->SetCDMProxy(aProxy); 182 } 183 184 void MediaDecoderStateMachineBase::SetIsLiveStream(bool aIsLiveStream) { 185 mIsLiveStream = aIsLiveStream; 186 } 187 188 bool MediaDecoderStateMachineBase::IsLiveStream() const { 189 return mIsLiveStream; 190 } 191 192 #undef INIT_MIRROR 193 #undef INIT_CANONICAL 194 #undef FMT 195 #undef LOG 196 #undef LOGV 197 #undef LOGW 198 #undef LOGE 199 200 } // namespace mozilla