Bug 1596777 - Hook up the SecondaryVideoContainer with state mirroring. r=alwu

This better follows how MediaDecoder and MediaDecoderStateMachine was
architected.

Differential Revision: https://phabricator.services.mozilla.com/D53710

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andreas Pehrson 2019-11-22 00:07:04 +00:00
parent 7adc7cdede
commit 3c62bb84d8
5 changed files with 44 additions and 40 deletions

View File

@ -502,12 +502,10 @@ void HTMLVideoElement::MaybeBeginCloningVisually() {
}
if (mDecoder) {
MediaDecoderStateMachine* mdsm = mDecoder->GetStateMachine();
VideoFrameContainer* container =
mVisualCloneTarget->GetVideoFrameContainer();
if (mdsm && container) {
mdsm->SetSecondaryVideoContainer(container);
mDecoder->SetCloningVisually(true);
if (container) {
mDecoder->SetSecondaryVideoContainer(container);
}
} else if (mSrcStream) {
VideoFrameContainer* container =
@ -522,11 +520,7 @@ void HTMLVideoElement::EndCloningVisually() {
MOZ_ASSERT(mVisualCloneTarget);
if (mDecoder) {
MediaDecoderStateMachine* mdsm = mDecoder->GetStateMachine();
if (mdsm) {
mdsm->SetSecondaryVideoContainer(nullptr);
mDecoder->SetCloningVisually(false);
}
mDecoder->SetSecondaryVideoContainer(nullptr);
} else if (mSrcStream) {
VideoFrameContainer* container =
mVisualCloneTarget->GetVideoFrameContainer();

View File

@ -301,7 +301,6 @@ MediaDecoder::MediaDecoder(MediaDecoderInit& aInit)
mIsElementInTree(false),
mForcedHidden(false),
mHasSuspendTaint(aInit.mHasSuspendTaint),
mIsCloningVisually(false),
mPlaybackRate(aInit.mPlaybackRate),
mLogicallySeeking(false, "MediaDecoder::mLogicallySeeking"),
INIT_MIRROR(mBuffered, TimeIntervals()),
@ -312,6 +311,7 @@ MediaDecoder::MediaDecoder(MediaDecoderInit& aInit)
INIT_CANONICAL(mPreservesPitch, aInit.mPreservesPitch),
INIT_CANONICAL(mLooping, aInit.mLooping),
INIT_CANONICAL(mSinkDevice, nullptr),
INIT_CANONICAL(mSecondaryVideoContainer, nullptr),
INIT_CANONICAL(mOutputCaptured, false),
INIT_CANONICAL(mOutputTracks, nsTArray<RefPtr<ProcessedMediaTrack>>()),
INIT_CANONICAL(mOutputPrincipal, PRINCIPAL_HANDLE_NONE),
@ -387,11 +387,8 @@ void MediaDecoder::Shutdown() {
// Ensure we always unregister asynchronously in order not to disrupt
// the hashtable iterating in MediaShutdownManager::Shutdown().
RefPtr<MediaDecoder> self = this;
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction("MediaDecoder::Shutdown", [self]() {
self->mVideoFrameContainer = nullptr;
self->ShutdownInternal();
});
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"MediaDecoder::Shutdown", [self]() { self->ShutdownInternal(); });
mAbstractMainThread->Dispatch(r.forget());
}
@ -533,13 +530,14 @@ void MediaDecoder::OnStoreDecoderBenchmark(const VideoInfo& aInfo) {
void MediaDecoder::ShutdownInternal() {
MOZ_ASSERT(NS_IsMainThread());
mVideoFrameContainer = nullptr;
mSecondaryVideoContainer = nullptr;
MediaShutdownManager::Instance().Unregister(this);
}
void MediaDecoder::FinishShutdown() {
MOZ_ASSERT(NS_IsMainThread());
SetStateMachine(nullptr);
mVideoFrameContainer = nullptr;
ShutdownInternal();
}
@ -1006,8 +1004,8 @@ void MediaDecoder::UpdateVideoDecodeMode() {
return;
}
// If mIsCloningVisually is set, never suspend the video decoder.
if (mIsCloningVisually) {
// If mSecondaryVideoContainer is set, never suspend the video decoder.
if (mSecondaryVideoContainer.Ref()) {
LOG("UpdateVideoDecodeMode(), set Normal because the element is cloning "
"itself visually to another video container.");
mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
@ -1072,11 +1070,15 @@ bool MediaDecoder::HasSuspendTaint() const {
return mHasSuspendTaint;
}
void MediaDecoder::SetCloningVisually(bool aIsCloningVisually) {
if (mIsCloningVisually != aIsCloningVisually) {
mIsCloningVisually = aIsCloningVisually;
UpdateVideoDecodeMode();
void MediaDecoder::SetSecondaryVideoContainer(
RefPtr<VideoFrameContainer> aSecondaryVideoContainer) {
MOZ_ASSERT(NS_IsMainThread());
AbstractThread::AutoEnter context(AbstractMainThread());
if (mSecondaryVideoContainer.Ref() == aSecondaryVideoContainer) {
return;
}
mSecondaryVideoContainer = std::move(aSecondaryVideoContainer);
UpdateVideoDecodeMode();
}
bool MediaDecoder::IsMediaSeekable() {

View File

@ -308,10 +308,11 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
// Returns true if the decoder can't participate in suspend-video-decoder.
bool HasSuspendTaint() const;
void SetCloningVisually(bool aIsCloningVisually);
void UpdateVideoDecodeMode();
void SetSecondaryVideoContainer(
RefPtr<VideoFrameContainer> aSecondaryVideoContainer);
void SetIsBackgroundVideoDecodingAllowed(bool aAllowed);
bool IsVideoDecodingSuspended() const;
@ -567,10 +568,6 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
// disabled.
bool mHasSuspendTaint;
// True if the decoder is sending video to a secondary container, and should
// not suspend the decoder.
bool mIsCloningVisually;
MediaDecoderOwner::NextFrameStatus mNextFrameStatus =
MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
@ -623,6 +620,10 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
// set.
Canonical<RefPtr<AudioDeviceInfo>> mSinkDevice;
// Set if the decoder is sending video to a secondary container. While set we
// should not suspend the decoder.
Canonical<RefPtr<VideoFrameContainer>> mSecondaryVideoContainer;
// Whether this MediaDecoder's output is captured. When captured, all decoded
// data must be played out through mOutputTracks.
Canonical<bool> mOutputCaptured;
@ -668,6 +669,10 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
AbstractCanonical<RefPtr<AudioDeviceInfo>>* CanonicalSinkDevice() {
return &mSinkDevice;
}
AbstractCanonical<RefPtr<VideoFrameContainer>>*
CanonicalSecondaryVideoContainer() {
return &mSecondaryVideoContainer;
}
AbstractCanonical<bool>* CanonicalOutputCaptured() {
return &mOutputCaptured;
}

View File

@ -2592,6 +2592,7 @@ RefPtr<ShutdownPromise> MediaDecoderStateMachine::ShutdownState::Enter() {
master->mPreservesPitch.DisconnectIfConnected();
master->mLooping.DisconnectIfConnected();
master->mSinkDevice.DisconnectIfConnected();
master->mSecondaryVideoContainer.DisconnectIfConnected();
master->mOutputCaptured.DisconnectIfConnected();
master->mOutputTracks.DisconnectIfConnected();
master->mOutputPrincipal.DisconnectIfConnected();
@ -2643,6 +2644,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
INIT_MIRROR(mPreservesPitch, true),
INIT_MIRROR(mLooping, false),
INIT_MIRROR(mSinkDevice, nullptr),
INIT_MIRROR(mSecondaryVideoContainer, nullptr),
INIT_MIRROR(mOutputCaptured, false),
INIT_MIRROR(mOutputTracks, nsTArray<RefPtr<ProcessedMediaTrack>>()),
INIT_MIRROR(mOutputPrincipal, PRINCIPAL_HANDLE_NONE),
@ -2679,6 +2681,8 @@ void MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) {
mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
mLooping.Connect(aDecoder->CanonicalLooping());
mSinkDevice.Connect(aDecoder->CanonicalSinkDevice());
mSecondaryVideoContainer.Connect(
aDecoder->CanonicalSecondaryVideoContainer());
mOutputCaptured.Connect(aDecoder->CanonicalOutputCaptured());
mOutputTracks.Connect(aDecoder->CanonicalOutputTracks());
mOutputPrincipal.Connect(aDecoder->CanonicalOutputPrincipal());
@ -2691,6 +2695,8 @@ void MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) {
&MediaDecoderStateMachine::PreservesPitchChanged);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
mWatchManager.Watch(mLooping, &MediaDecoderStateMachine::LoopingChanged);
mWatchManager.Watch(mSecondaryVideoContainer,
&MediaDecoderStateMachine::UpdateSecondaryVideoContainer);
mWatchManager.Watch(mOutputCaptured,
&MediaDecoderStateMachine::UpdateOutputCaptured);
mWatchManager.Watch(mOutputTracks,
@ -3613,15 +3619,10 @@ RefPtr<GenericPromise> MediaDecoderStateMachine::SetSink(
return GenericPromise::CreateAndResolve(wasPlaying, __func__);
}
void MediaDecoderStateMachine::SetSecondaryVideoContainer(
const RefPtr<VideoFrameContainer>& aSecondary) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<MediaDecoderStateMachine> self = this;
Unused << InvokeAsync(OwnerThread(), __func__, [self, aSecondary]() {
self->mMediaSink->SetSecondaryVideoContainer(aSecondary);
return GenericPromise::CreateAndResolve(true, __func__);
});
void MediaDecoderStateMachine::UpdateSecondaryVideoContainer() {
MOZ_ASSERT(OnTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(mMediaSink);
mMediaSink->SetSecondaryVideoContainer(mSecondaryVideoContainer.Ref());
}
TimeUnit MediaDecoderStateMachine::AudioEndTime() const {

View File

@ -269,9 +269,6 @@ class MediaDecoderStateMachine
RefPtr<GenericPromise> InvokeSetSink(RefPtr<AudioDeviceInfo> aSink);
void SetSecondaryVideoContainer(
const RefPtr<VideoFrameContainer>& aSecondary);
private:
class StateObject;
class DecodeMetadataState;
@ -375,6 +372,7 @@ class MediaDecoderStateMachine
void SetPlaybackRate(double aPlaybackRate);
void PreservesPitchChanged();
void LoopingChanged();
void UpdateSecondaryVideoContainer();
void UpdateOutputCaptured();
void OutputTracksChanged();
void OutputPrincipalChanged();
@ -708,6 +706,10 @@ class MediaDecoderStateMachine
// set.
Mirror<RefPtr<AudioDeviceInfo>> mSinkDevice;
// Set if the decoder is sending video to a secondary container. While set we
// should not suspend the decoder.
Mirror<RefPtr<VideoFrameContainer>> mSecondaryVideoContainer;
// Whether all output should be captured into mOutputTracks. While true, the
// media sink will only play if there are output tracks.
Mirror<bool> mOutputCaptured;