diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index b2192518105f..372f17d151de 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2524,15 +2524,13 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
// It's value may have changed, so update it.
UpdatePreloadAction();
}
+ mElementInTreeState = ELEMENT_INTREE;
+
if (mDecoder) {
// When the MediaElement is binding to tree, the dormant status is
// aligned to document's hidden status.
- nsIDocument* ownerDoc = OwnerDoc();
- if (ownerDoc) {
- mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
- }
+ mDecoder->NotifyOwnerActivityChanged();
}
- mElementInTreeState = ELEMENT_INTREE;
return rv;
}
@@ -2543,12 +2541,14 @@ void HTMLMediaElement::UnbindFromTree(bool aDeep,
if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY)
Pause();
- if (mDecoder) {
- mDecoder->SetDormantIfNecessary(true);
- }
mElementInTreeState = ELEMENT_NOT_INTREE_HAD_INTREE;
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
+
+ if (mDecoder) {
+ MOZ_ASSERT(IsHidden());
+ mDecoder->NotifyOwnerActivityChanged();
+ }
}
/* static */
@@ -3519,6 +3519,21 @@ void HTMLMediaElement::CheckAutoplayDataReady()
}
}
+bool HTMLMediaElement::IsActive()
+{
+ nsIDocument* ownerDoc = OwnerDoc();
+ return ownerDoc && ownerDoc->IsActive() && ownerDoc->IsVisible();
+}
+
+bool HTMLMediaElement::IsHidden()
+{
+ if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) {
+ return true;
+ }
+ nsIDocument* ownerDoc = OwnerDoc();
+ return !ownerDoc || ownerDoc->Hidden();
+}
+
VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
{
if (mVideoFrameContainer)
@@ -3698,15 +3713,7 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
if (mDecoder) {
mDecoder->SetElementVisibility(!ownerDoc->Hidden());
-
- if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) {
- mDecoder->SetDormantIfNecessary(true);
- } else if (mElementInTreeState == ELEMENT_NOT_INTREE ||
- mElementInTreeState == ELEMENT_INTREE) {
- // The MediaElement had never been binded to tree, or in the tree now,
- // align to document.
- mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
- }
+ mDecoder->NotifyOwnerActivityChanged();
}
// SetVisibilityState will update mMuted with MUTED_BY_AUDIO_CHANNEL via the
@@ -3716,10 +3723,9 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
AutoNoJSAPI nojsapi;
mAudioChannelAgent->SetVisibilityState(!ownerDoc->Hidden());
}
- bool suspendEvents = !ownerDoc->IsActive() || !ownerDoc->IsVisible();
- bool pauseElement = suspendEvents || (mMuted & MUTED_BY_AUDIO_CHANNEL);
+ bool pauseElement = !IsActive() || (mMuted & MUTED_BY_AUDIO_CHANNEL);
- SuspendOrResumeElement(pauseElement, suspendEvents);
+ SuspendOrResumeElement(pauseElement, !IsActive());
AddRemoveSelfReference();
}
diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h
index 3f2e52c2e92f..477bbc1f14ca 100644
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -211,6 +211,10 @@ public:
// suspended the channel.
virtual void NotifySuspendedByCache(bool aIsSuspended) MOZ_FINAL MOZ_OVERRIDE;
+ virtual bool IsActive() MOZ_FINAL MOZ_OVERRIDE;
+
+ virtual bool IsHidden() MOZ_FINAL MOZ_OVERRIDE;
+
// Called by the media decoder and the video frame to get the
// ImageContainer containing the video data.
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
@@ -374,7 +378,7 @@ public:
// Called by the media decoder object, on the main thread,
// when the connection between Rtsp server and client gets lost.
- void ResetConnectionState() MOZ_FINAL MOZ_OVERRIDE;
+ virtual void ResetConnectionState() MOZ_FINAL MOZ_OVERRIDE;
// XPCOM GetPreload() is OK
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp
index 10c7a5b2c708..8fba87581f23 100644
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -118,7 +118,7 @@ NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
NS_IMPL_ISUPPORTS(MediaDecoder, nsIObserver)
-void MediaDecoder::SetDormantIfNecessary(bool aDormant)
+void MediaDecoder::NotifyOwnerActivityChanged()
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
@@ -129,7 +129,28 @@ void MediaDecoder::SetDormantIfNecessary(bool aDormant)
return;
}
- if(aDormant) {
+ if (!mOwner) {
+ NS_WARNING("MediaDecoder without a decoder owner, can't update dormant");
+ return;
+ }
+
+ bool prevDormant = mIsDormant;
+ mIsDormant = false;
+ if (!mOwner->IsActive() && mOwner->GetVideoFrameContainer()) {
+ mIsDormant = true;
+ }
+#ifdef MOZ_WIDGET_GONK
+ if (mOwner->IsHidden() && mOwner->GetVideoFrameContainer()) {
+ mIsDormant = true;
+ }
+#endif
+
+ if (prevDormant == mIsDormant) {
+ // No update to dormant state
+ return;
+ }
+
+ if (mIsDormant) {
// enter dormant state
mDecoderStateMachine->SetDormant(true);
@@ -450,7 +471,8 @@ MediaDecoder::MediaDecoder() :
mShuttingDown(false),
mPausedForPlaybackRateNull(false),
mMinimizePreroll(false),
- mMediaTracksConstructed(false)
+ mMediaTracksConstructed(false),
+ mIsDormant(false)
{
MOZ_COUNT_CTOR(MediaDecoder);
MOZ_ASSERT(NS_IsMainThread());
diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h
index d07e12e5d3a0..92dc83ce1c50 100644
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -360,11 +360,12 @@ public:
// called.
virtual nsresult Play();
- // Set/Unset dormant state if necessary.
+ // Notify activity of the decoder owner is changed.
+ // Based on the activity, dormant state is updated.
// Dormant state is a state to free all scarce media resources
// (like hw video codec), did not decoding and stay dormant.
// It is used to share scarece media resources in system.
- virtual void SetDormantIfNecessary(bool aDormant);
+ virtual void NotifyOwnerActivityChanged();
// Pause video playback.
virtual void Pause();
@@ -1215,6 +1216,9 @@ protected:
// Stores media info, including info of audio tracks and video tracks, should
// only be accessed from main thread.
nsAutoPtr mInfo;
+
+ // True if MediaDecoder is in dormant state.
+ bool mIsDormant;
};
} // namespace mozilla
diff --git a/dom/media/MediaDecoderOwner.h b/dom/media/MediaDecoderOwner.h
index 815cd1ce52b9..23f7e9634440 100644
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -120,6 +120,12 @@ public:
// HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA.
virtual void UpdateReadyStateForData(NextFrameStatus aNextFrame) = 0;
+ // Check if the decoder owner is active.
+ virtual bool IsActive() = 0;
+
+ // Check if the decoder owner is hidden.
+ virtual bool IsHidden() = 0;
+
// Called by the media decoder and the video frame to get the
// ImageContainer containing the video data.
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;