Bug 1282710 part 1 - implement the suspend and resume logics in HTMLMediaElement.cpp according to visibility events; r=cpearce,kamidphish
MozReview-Commit-ID: 4SyqzA1dnPB
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5815,10 +5815,76 @@ HTMLMediaElement::IsAudible() const
// Silent audio track.
if (!mIsAudioTrackAudible) {
return false;
}
return true;
}
+static const char* VisibilityString(Visibility aVisibility) {
+ switch(aVisibility) {
+ case Visibility::UNTRACKED: {
+ return "UNTRACKED";
+ }
+ case Visibility::NONVISIBLE: {
+ return "NONVISIBLE";
+ }
+ case Visibility::MAY_BECOME_VISIBLE: {
+ return "MAY_BECOME_VISIBLE";
+ }
+ case Visibility::IN_DISPLAYPORT: {
+ return "IN_DISPLAYPORT";
+ }
+ }
+
+ return "NAN";
+}
+
+// The visibility enumeration contains three states:
+// {NONVISIBLE, MAY_BECOME_VISIBLE, IN_DISPLAYPORT}.
+// Here, I implement a conservative mechanism:
+// (1) {MAY_BECOME_VISIBLE, IN_DISPLAYPORT} -> NONVISIBLE:
+// notify the decoder to suspend.
+// (2) {NONVISIBLE, MAY_BECOME_VISIBLE} -> IN_DISPLAYPORT:
+// notify the decoder to resume.
+// (3) IN_DISPLAYPORT -> MAY_BECOME_VISIBLE:
+// do nothing here because users might scroll back immediately.
+// (4) NONVISIBLE -> MAY_BECOME_VISIBLE:
+// notify the decoder to resume because users might continue their scroll
+// direction and the video might be IN_DISPLAYPORT soon.
+void
+HTMLMediaElement::OnVisibilityChange(Visibility aOldVisibility,
+ Visibility aNewVisibility)
+{
+ LOG(LogLevel::Debug, ("OnVisibilityChange(): %s -> %s\n",
+ VisibilityString(aOldVisibility),VisibilityString(aNewVisibility)));
+
+ if (!mDecoder) {
+ return;
+ }
+
+ switch (aNewVisibility) {
+ case Visibility::UNTRACKED: {
+ MOZ_ASSERT_UNREACHABLE("Shouldn't notify for untracked visibility");
+ break;
+ }
+ case Visibility::NONVISIBLE: {
+ mDecoder->NotifyOwnerActivityChanged(false);
+ break;
+ }
+ case Visibility::MAY_BECOME_VISIBLE: {
+ if (aOldVisibility == Visibility::NONVISIBLE) {
+ mDecoder->NotifyOwnerActivityChanged(true);
+ } else if (aOldVisibility == Visibility::IN_DISPLAYPORT) {
+ // Do nothing.
+ }
+ break;
+ }
+ case Visibility::IN_DISPLAYPORT: {
+ mDecoder->NotifyOwnerActivityChanged(true);
+ break;
+ }
+ }
+
+}
} // namespace dom
} // namespace mozilla
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
@@ -18,18 +18,21 @@
* @status UNDER_DEVELOPMENT
*/
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
%{C++
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
+#include "Visibility.h"
%}
+native Visibility(mozilla::Visibility);
+
[uuid(c041d76c-15ce-47ad-b61d-e8755a6db638)]
interface nsIDOMHTMLMediaElement : nsISupports
{
// error state
readonly attribute nsIDOMMediaError error;
// network state
attribute DOMString src;
@@ -124,9 +127,19 @@ interface nsIDOMHTMLMediaElement : nsISu
attribute DOMString mozAudioChannelType;
// In addition the media element has this new events:
// * onmozinterruptbegin - called when the media element is interrupted
// because of the audiochannel manager.
// * onmozinterruptend - called when the interruption is concluded
[notxpcom] boolean isVideo();
+
+ /**
+ * Called by layout to announce when the frame associated with this content
+ * has changed its visibility state.
+ *
+ * @param aOldVisibility The previous visibility state.
+ * @param aNewVisibility The new visibility state.
+ */
+ [noscript, notxpcom] void onVisibilityChange(in Visibility aOldVisibility,
+ in Visibility aNewVisibility);
};