Bug 1282710 part 1 - implement the suspend and resume logics in HTMLMediaElement.cpp according to visibility events; r=cpearce,kamidphish draft
authorKaku Kuo <tkuo@mozilla.com>
Mon, 04 Jul 2016 13:26:40 +0800
changeset 383429 9bb393314e33d7352a485d6013540ae87b2aeb9e
parent 383328 39dffbba764210b25bfc1e749b4f16db77fa0d46
child 383430 4e9de97f321492a4035e80312b682cbd0f20980d
push id22024
push usertkuo@mozilla.com
push dateMon, 04 Jul 2016 05:32:04 +0000
reviewerscpearce, kamidphish
bugs1282710
milestone50.0a1
Bug 1282710 part 1 - implement the suspend and resume logics in HTMLMediaElement.cpp according to visibility events; r=cpearce,kamidphish MozReview-Commit-ID: 4SyqzA1dnPB
dom/html/HTMLMediaElement.cpp
dom/interfaces/html/nsIDOMHTMLMediaElement.idl
--- 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);
 };