Bug 865407 - Part 5: Move update display of cues code to TextTrackManager. r=bz, r=rillian
authorRick Eyre <rick.eyre@hotmail.com>
Thu, 12 Dec 2013 12:02:17 -0500
changeset 163347 9264d50055ea68c141bd00ce7bcb46c861d90490
parent 163346 401b8593a881f7c98d42129395b7f5abdc6343ba
child 163348 f5abf3eb7b2eeaccbdcc461d9a0982199c15065c
push id25993
push userkwierso@gmail.com
push dateTue, 14 Jan 2014 23:24:56 +0000
treeherdermozilla-central@4e671e3183c4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, rillian
bugs865407
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 865407 - Part 5: Move update display of cues code to TextTrackManager. r=bz, r=rillian
content/html/content/src/HTMLMediaElement.cpp
content/html/content/src/TextTrackManager.cpp
content/html/content/src/TextTrackManager.h
content/media/TextTrack.cpp
content/media/TextTrack.h
content/media/TextTrackCue.cpp
content/media/TextTrackCue.h
content/media/TextTrackCueList.cpp
content/media/TextTrackCueList.h
content/media/TextTrackList.cpp
content/media/TextTrackList.h
content/media/webvtt/WebVTTParserWrapper.js
content/media/webvtt/nsIWebVTTParserWrapper.idl
layout/style/html.css
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3672,22 +3672,22 @@ void HTMLMediaElement::FireTimeUpdate(bo
   }
   if (mFragmentEnd >= 0.0 && time >= mFragmentEnd) {
     Pause();
     mFragmentEnd = -1.0;
     mFragmentStart = -1.0;
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
 
-  // Update visible text tracks.
+  // Update the cues displaying on the video.
   // Here mTextTrackManager can be null if the cycle collector has unlinked
   // us before our parent. In that case UnbindFromTree will call us
   // when our parent is unlinked.
   if (mTextTrackManager) {
-    mTextTrackManager->Update(time);
+    mTextTrackManager->UpdateCueDisplay();
   }
 }
 
 void HTMLMediaElement::GetCurrentSpec(nsCString& aString)
 {
   if (mLoadingSrc) {
     mLoadingSrc->GetSpec(aString);
   } else {
--- a/content/html/content/src/TextTrackManager.cpp
+++ b/content/html/content/src/TextTrackManager.cpp
@@ -3,33 +3,50 @@
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/TextTrackManager.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLTrackElement.h"
+#include "mozilla/dom/TextTrack.h"
+#include "mozilla/dom/TextTrackCue.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "nsComponentManagerUtils.h"
+#include "nsVideoFrame.h"
+#include "nsIFrame.h"
+#include "nsTArrayHelpers.h"
+#include "nsIWebVTTParserWrapper.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_3(TextTrackManager, mTextTracks,
                            mPendingTextTracks, mNewCues)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release)
 
+StaticRefPtr<nsIWebVTTParserWrapper> TextTrackManager::sParserWrapper;
+
 TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
   : mMediaElement(aMediaElement)
 {
   MOZ_COUNT_CTOR(TextTrackManager);
   mNewCues = new TextTrackCueList(mMediaElement->OwnerDoc()->GetParentObject());
   mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
   mPendingTextTracks =
     new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
+
+  if (!sParserWrapper) {
+    nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
+      do_CreateInstance(NS_WEBVTTPARSERWRAPPER_CONTRACTID);
+    sParserWrapper = parserWrapper;
+    ClearOnShutdown(&sParserWrapper);
+  }
 }
 
 TextTrackManager::~TextTrackManager()
 {
   MOZ_COUNT_DTOR(TextTrackManager);
 }
 
 TextTrackList*
@@ -81,19 +98,52 @@ TextTrackManager::RemoveTextTrack(TextTr
 
 void
 TextTrackManager::DidSeek()
 {
   mTextTracks->DidSeek();
 }
 
 void
-TextTrackManager::Update(double aTime)
+TextTrackManager::UpdateCueDisplay()
 {
-  mTextTracks->Update(aTime);
+  nsIFrame* frame = mMediaElement->GetPrimaryFrame();
+  if (!frame) {
+    return;
+  }
+
+  nsVideoFrame* videoFrame = do_QueryFrame(frame);
+  if (!videoFrame) {
+    return;
+  }
+
+  nsCOMPtr<nsIContent> overlay = videoFrame->GetCaptionOverlay();
+  if (!overlay) {
+    return;
+  }
+
+  nsTArray<nsRefPtr<TextTrackCue> > activeCues;
+  mTextTracks->GetAllActiveCues(activeCues);
+
+  if (activeCues.Length() > 0) {
+    nsCOMPtr<nsIWritableVariant> jsCues =
+      do_CreateInstance("@mozilla.org/variant;1");
+
+    jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
+                       &NS_GET_IID(nsIDOMEventTarget),
+                       activeCues.Length(),
+                       static_cast<void*>(activeCues.Elements()));
+
+    nsPIDOMWindow* window = mMediaElement->OwnerDoc()->GetWindow();
+    if (window) {
+      sParserWrapper->ProcessCues(window, jsCues, overlay);
+    }
+  } else if (overlay->Length() > 0) {
+    nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
+  }
 }
 
 void
 TextTrackManager::AddCue(TextTrackCue& aCue)
 {
   mNewCues->AddCue(aCue);
 }
 
--- a/content/html/content/src/TextTrackManager.h
+++ b/content/html/content/src/TextTrackManager.h
@@ -6,21 +6,26 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_TextTrackManager_h
 #define mozilla_dom_TextTrackManager_h
 
 #include "mozilla/dom/TextTrack.h"
 #include "mozilla/dom/TextTrackList.h"
 #include "mozilla/dom/TextTrackCueList.h"
+#include "mozilla/StaticPtr.h"
+
+class nsIWebVTTParserWrapper;
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
+class TextTrack;
+class TextTrackCue;
 
 class TextTrackManager
 {
 public:
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TextTrackManager)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TextTrackManager);
 
   TextTrackManager(HTMLMediaElement *aMediaElement);
@@ -32,32 +37,60 @@ public:
                                            const nsAString& aLanguage);
   void AddTextTrack(TextTrack* aTextTrack);
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
   void DidSeek();
 
   void AddCue(TextTrackCue& aCue);
   void AddCues(TextTrack* aTextTrack);
 
-  // Update the display of cues on the video as per the current play back time
-  // of aTime.
-  void Update(double aTime);
+  /**
+   * Overview of WebVTT cuetext and anonymous content setup.
+   *
+   * WebVTT nodes are the parsed version of WebVTT cuetext. WebVTT cuetext is
+   * the portion of a WebVTT cue that specifies what the caption will actually
+   * show up as on screen.
+   *
+   * WebVTT cuetext can contain markup that loosely relates to HTML markup. It
+   * can contain tags like <b>, <u>, <i>, <c>, <v>, <ruby>, <rt>, <lang>,
+   * including timestamp tags.
+   *
+   * When the caption is ready to be displayed the WebVTT nodes are converted
+   * over to anonymous DOM content. <i>, <u>, <b>, <ruby>, and <rt> all become
+   * HTMLElements of their corresponding HTML markup tags. <c> and <v> are
+   * converted to <span> tags. Timestamp tags are converted to XML processing
+   * instructions. Additionally, all cuetext tags support specifying of classes.
+   * This takes the form of <foo.class.subclass>. These classes are then parsed
+   * and set as the anonymous content's class attribute.
+   *
+   * Rules on constructing DOM objects from WebVTT nodes can be found here
+   * http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules.
+   * Current rules are taken from revision on April 15, 2013.
+   */
+
+  /**
+   * Converts the TextTrackCue's cuetext into a tree of DOM objects and attaches
+   * it to a div on it's owning TrackElement's MediaElement's caption overlay.
+   */
+  void UpdateCueDisplay();
 
   void PopulatePendingList();
 
 private:
   // The HTMLMediaElement that this TextTrackManager manages the TextTracks of.
   // This is a weak reference as the life time of TextTrackManager is dependent
   // on the HTMLMediaElement, so it should not be trying to hold the
   // HTMLMediaElement alive.
   HTMLMediaElement* mMediaElement;
   // List of the TextTrackManager's owning HTMLMediaElement's TextTracks.
   nsRefPtr<TextTrackList> mTextTracks;
   // List of text track objects awaiting loading.
   nsRefPtr<TextTrackList> mPendingTextTracks;
   // List of newly introduced Text Track cues.
   nsRefPtr<TextTrackCueList> mNewCues;
+
+  static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TextTrackManager_h
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -67,24 +67,16 @@ TextTrack::SetDefaultSettings()
   mCueList = new TextTrackCueList(mParent);
   mActiveCueList = new TextTrackCueList(mParent);
   mRegionList = new TextTrackRegionList(mParent);
   mCuePos = 0;
   mDirty = false;
   mReadyState = HTMLTrackElement::NONE;
 }
 
-void
-TextTrack::Update(double aTime)
-{
-  if (mCueList) {
-    mCueList->Update(aTime);
-  }
-}
-
 JSObject*
 TextTrack::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackBinding::Wrap(aCx, aScope, this);
 }
 
 void
 TextTrack::SetMode(TextTrackMode aValue)
--- a/content/media/TextTrack.h
+++ b/content/media/TextTrack.h
@@ -94,19 +94,16 @@ public:
   }
 
   uint16_t ReadyState() const;
   void SetReadyState(uint16_t aState);
 
   void AddRegion(TextTrackRegion& aRegion);
   void RemoveRegion(const TextTrackRegion& aRegion, ErrorResult& aRv);
 
-  // Time is in seconds.
-  void Update(double aTime);
-
   void AddCue(TextTrackCue& aCue);
   void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
   void CueChanged(TextTrackCue& aCue);
   void SetDirty() { mDirty = true; }
 
   IMPL_EVENT_HANDLER(cuechange)
 
 private:
--- a/content/media/TextTrackCue.cpp
+++ b/content/media/TextTrackCue.cpp
@@ -1,17 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLTrackElement.h"
 #include "mozilla/dom/TextTrackCue.h"
-#include "nsIFrame.h"
-#include "nsVideoFrame.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 
 // Alternate value for the 'auto' keyword.
 #define WEBVTT_AUTO -1
 
 namespace mozilla {
 namespace dom {
@@ -96,68 +94,16 @@ TextTrackCue::StashDocument(nsISupports*
   }
   mDocument = window->GetDoc();
   if (!mDocument) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   return NS_OK;
 }
 
-void
-TextTrackCue::CreateCueOverlay()
-{
-  nsCOMPtr<nsINodeInfo> nodeInfo =
-    mDocument->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div,
-                                              nullptr,
-                                              kNameSpaceID_XHTML,
-                                              nsIDOMNode::ELEMENT_NODE);
-  mDisplayState = NS_NewHTMLDivElement(nodeInfo.forget());
-  mDisplayState->SetClassName(NS_LITERAL_STRING("caption-text"));
-}
-
-void
-TextTrackCue::RenderCue()
-{
-  nsRefPtr<DocumentFragment> frag = GetCueAsHTML();
-  if (!frag || !mTrackElement) {
-    return;
-  }
-
-  if (!mDisplayState) {
-    CreateCueOverlay();
-  }
-
-  HTMLMediaElement* parent = mTrackElement->mMediaParent;
-  if (!parent) {
-    return;
-  }
-
-  nsIFrame* frame = parent->GetPrimaryFrame();
-  if (!frame) {
-    return;
-  }
-
-  nsVideoFrame* videoFrame = do_QueryFrame(frame);
-  if (!videoFrame) {
-    return;
-  }
-
-  nsIContent* overlay =  videoFrame->GetCaptionOverlay();
-  if (!overlay) {
-    return;
-  }
-
-  ErrorResult rv;
-  nsContentUtils::SetNodeTextContent(overlay, EmptyString(), true);
-  nsContentUtils::SetNodeTextContent(mDisplayState, EmptyString(), true);
-
-  mDisplayState->nsINode::AppendChild(*frag, rv);
-  overlay->AppendChild(*mDisplayState, rv);
-}
-
 already_AddRefed<DocumentFragment>
 TextTrackCue::GetCueAsHTML()
 {
   MOZ_ASSERT(mDocument);
 
   if (!sParserWrapper) {
     nsresult rv;
     nsCOMPtr<nsIWebVTTParserWrapper> parserWrapper =
--- a/content/media/TextTrackCue.h
+++ b/content/media/TextTrackCue.h
@@ -315,60 +315,29 @@ public:
   }
 
   const nsAString& Id() const
   {
     return mId;
   }
 
   /**
-   * Overview of WebVTT cuetext and anonymous content setup.
-   *
-   * WebVTT nodes are the parsed version of WebVTT cuetext. WebVTT cuetext is
-   * the portion of a WebVTT cue that specifies what the caption will actually
-   * show up as on screen.
-   *
-   * WebVTT cuetext can contain markup that loosely relates to HTML markup. It
-   * can contain tags like <b>, <u>, <i>, <c>, <v>, <ruby>, <rt>, <lang>,
-   * including timestamp tags.
-   *
-   * When the caption is ready to be displayed the WebVTT nodes are converted
-   * over to anonymous DOM content. <i>, <u>, <b>, <ruby>, and <rt> all become
-   * HTMLElements of their corresponding HTML markup tags. <c> and <v> are
-   * converted to <span> tags. Timestamp tags are converted to XML processing
-   * instructions. Additionally, all cuetext tags support specifying of classes.
-   * This takes the form of <foo.class.subclass>. These classes are then parsed
-   * and set as the anonymous content's class attribute.
-   *
-   * Rules on constructing DOM objects from WebVTT nodes can be found here
-   * http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules.
-   * Current rules are taken from revision on April 15, 2013.
-   */
-
-  /**
-   * Converts the TextTrackCue's cuetext into a tree of DOM objects and attaches
-   * it to a div on it's owning TrackElement's MediaElement's caption overlay.
-   */
-  void RenderCue();
-
-  /**
    * Produces a tree of anonymous content based on the tree of the processed
    * cue text.
    *
    * Returns a DocumentFragment that is the head of the tree of anonymous
    * content.
    */
   already_AddRefed<DocumentFragment> GetCueAsHTML();
 
   void SetTrackElement(HTMLTrackElement* aTrackElement);
 
 private:
   void CueChanged();
   void SetDefaultCueSettings();
-  void CreateCueOverlay();
   nsresult StashDocument(nsISupports* aGlobal);
 
   nsRefPtr<nsIDocument> mDocument;
   nsString mText;
   double mStartTime;
   double mEndTime;
 
   nsRefPtr<TextTrack> mTrack;
--- a/content/media/TextTrackCueList.cpp
+++ b/content/media/TextTrackCueList.cpp
@@ -33,27 +33,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 TextTrackCueList::TextTrackCueList(nsISupports* aParent) : mParent(aParent)
 {
   SetIsDOMBinding();
 }
 
-void
-TextTrackCueList::Update(double aTime)
-{
-  const uint32_t length = mList.Length();
-  for (uint32_t i = 0; i < length; i++) {
-    if (aTime > mList[i]->StartTime() && aTime < mList[i]->EndTime()) {
-      mList[i]->RenderCue();
-    }
-  }
-}
-
 JSObject*
 TextTrackCueList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackCueListBinding::Wrap(aCx, aScope, this);
 }
 
 TextTrackCue*
 TextTrackCueList::IndexedGetter(uint32_t aIndex, bool& aFound)
--- a/content/media/TextTrackCueList.h
+++ b/content/media/TextTrackCueList.h
@@ -36,19 +36,16 @@ public:
     return mParent;
   }
 
   uint32_t Length() const
   {
     return mList.Length();
   }
 
-  // Time is in seconds.
-  void Update(double aTime);
-
   TextTrackCue* IndexedGetter(uint32_t aIndex, bool& aFound);
   TextTrackCue* operator[](uint32_t aIndex);
   TextTrackCue* GetCueById(const nsAString& aId);
 
   // Adds a cue to mList by performing an insertion sort on mList.
   // We expect most files to already be sorted, so an insertion sort starting
   // from the end of the current array should be more efficient than a general
   // sort step after all cues are loaded.
--- a/content/media/TextTrackList.cpp
+++ b/content/media/TextTrackList.cpp
@@ -23,25 +23,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 TextTrackList::TextTrackList(nsISupports* aGlobal) : mGlobal(aGlobal)
 {
   SetIsDOMBinding();
 }
 
 void
-TextTrackList::Update(double aTime)
-{
-  uint32_t length = Length(), i;
-  for (i = 0; i < length; i++) {
-    mTextTracks[i]->Update(aTime);
-  }
-}
-
-void
 TextTrackList::GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
 {
   nsTArray< nsRefPtr<TextTrackCue> > cues;
   for (uint32_t i = 0; i < Length(); i++) {
     if (mTextTracks[i]->Mode() != TextTrackMode::Disabled) {
       mTextTracks[i]->GetActiveCueArray(cues);
       aCues.AppendElements(cues);
     }
--- a/content/media/TextTrackList.h
+++ b/content/media/TextTrackList.h
@@ -33,19 +33,16 @@ public:
     return mGlobal;
   }
 
   uint32_t Length() const
   {
     return mTextTracks.Length();
   }
 
-  // Time is in seconds.
-  void Update(double aTime);
-
   // Get all the current active cues.
   void GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
 
   TextTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
 
   already_AddRefed<TextTrack> AddTextTrack(HTMLMediaElement* aMediaElement,
                                            TextTrackKind aKind,
                                            const nsAString& aLabel,
--- a/content/media/webvtt/WebVTTParserWrapper.js
+++ b/content/media/webvtt/WebVTTParserWrapper.js
@@ -45,16 +45,21 @@ WebVTTParserWrapper.prototype =
     this.parser.onregion = callback.onRegion;
   },
 
   convertCueToDOMTree: function(window, cue)
   {
     return WebVTTParser.convertCueToDOMTree(window, cue.text);
   },
 
+  processCues: function(window, cues, overlay)
+  {
+    // TODO: Call prcoess cues on vtt.js
+  },
+
   classDescription: "Wrapper for the JS WebVTTParser (vtt.js)",
   classID: Components.ID(WEBVTTPARSERWRAPPER_CID),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebVTTParserWrapper]),
   classInfo: XPCOMUtils.generateCI({
     classID:    WEBVTTPARSERWRAPPER_CID,
     contractID: WEBVTTPARSERWRAPPER_CONTRACTID,
     interfaces: [Ci.nsIWebVTTParserWrapper]
   })
--- a/content/media/webvtt/nsIWebVTTParserWrapper.idl
+++ b/content/media/webvtt/nsIWebVTTParserWrapper.idl
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMHTMLElement;
 interface nsIWebVTTListener;
 interface nsIDOMWindow;
+interface nsIVariant;
 
 /**
  * Interface for a wrapper of a JS WebVTT parser (vtt.js).
  */
 [scriptable, uuid(1604a67f-3b72-4027-bcba-6dddd5be6b10)]
 interface nsIWebVTTParserWrapper : nsISupports
 {
   /**
@@ -56,13 +57,31 @@ interface nsIWebVTTParserWrapper : nsISu
    *
    * @param window A window object with which the document fragment will be
    *               created.
    * @param cue    The cue whose content will be converted to a document
    *               fragment.
    */
   nsIDOMHTMLElement convertCueToDOMTree(in nsIDOMWindow window,
                                         in nsISupports cue);
+
+
+  /**
+   * Compute the display state of the VTTCues in cues along with any VTTRegions
+   * that they might be in. First, it computes the positioning and styling of
+   * the cues and regions passed and converts them into a DOM tree rooted at
+   * a containing HTMLDivElement. It then adjusts those computed divs for
+   * overlap avoidance using the dimensions of 'overlay'. Finally, it adds the
+   * computed divs to the VTTCues display state property for use later.
+   *
+   * @param window  A window object with which it will create the DOM tree
+   *                and containing div element.
+   * @param cues    An array of VTTCues who need there display state to be
+   *                computed.
+   * @param overlay The HTMLElement that the cues will be displayed within.
+   */
+  void processCues(in nsIDOMWindow window, in nsIVariant cues,
+                   in nsISupports overlay);
 };
 
 %{C++
 #define NS_WEBVTTPARSERWRAPPER_CONTRACTID "@mozilla.org/webvttParserWrapper;1"
 %}
--- a/layout/style/html.css
+++ b/layout/style/html.css
@@ -723,35 +723,19 @@ audio:not([controls]) {
 *|*::-moz-html-canvas-content {
   display: block !important;
   /* we want to be an absolute and fixed container */
   -moz-transform: translate(0) !important;
 }
 
 video > .caption-box {
   position: relative;
-  pointer-events: none;
-}
-
-video > div .caption-text {
-  position: absolute;
-  bottom: 24px;
-  padding: 5px;
-  left: 0;
-  right: 0;
-  text-align: center;
-  pointer-events: auto;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 20px;
-  color: white;
-  text-shadow:
-    -2px -2px 1px #000,
-    2px -2px 1px #000,
-    -2px 2px 1px #000,
-    2px 2px 1px #000;
+  overflow: hidden;
+  padding: 1.5%;
+  box-sizing: border-box;
 }
 
 /* emulation of non-standard HTML <marquee> tag */
 marquee {
   width: -moz-available;
   display: inline-block;
   vertical-align: text-bottom;
   text-align: start;