Bug 1547892 - Load video element in VideoDocument slightly later during load. r=bzbarsky
authorChris Pearce <cpearce@mozilla.com>
Tue, 14 May 2019 04:27:49 +0000
changeset 532554 2d94f58711b3c1b501d72ed05845198fc3aeb6e8
parent 532553 23396874909ff1d79eb198fa300c81bd66aafa2b
child 532555 aa14d710b4ccd7ff72693f988c006aff700b9183
push id11270
push userrgurzau@mozilla.com
push dateWed, 15 May 2019 15:07:19 +0000
treeherdermozilla-beta@571bc76da583 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1547892
milestone68.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 1547892 - Load video element in VideoDocument slightly later during load. r=bzbarsky Currently when we create the video inside a VideoDocument, the PresShell isn't created yet. This means the video element can't access information about the compositor, which means it doesn't know whether it can create a hardware accelerated video decoder, and so we end up falling back to using a software decoder. So this patch moves the creation of the video element to slightly later in the load of a VideoDocument, so that the PresShell is available when we create the VideoDocument's video element. This means VideoDocuments's video decoder can be hardware accelerated Differential Revision: https://phabricator.services.mozilla.com/D30614
dom/html/MediaDocument.h
dom/html/PluginDocument.cpp
dom/html/VideoDocument.cpp
--- a/dom/html/MediaDocument.h
+++ b/dom/html/MediaDocument.h
@@ -48,17 +48,17 @@ class MediaDocument : public nsHTMLDocum
   // Check whether initial setup has been done.
   MOZ_MUST_USE bool InitialSetupHasBeenDone() const {
     return mDidInitialDocumentSetup;
   }
 
   virtual nsresult CreateSyntheticDocument();
 
   friend class MediaDocumentStreamListener;
-  nsresult StartLayout();
+  virtual nsresult StartLayout();
 
   void GetFileName(nsAString& aResult, nsIChannel* aChannel);
 
   nsresult LinkStylesheet(const nsAString& aStylesheet);
   nsresult LinkScript(const nsAString& aScript);
 
   // |aFormatNames[]| needs to have four elements in the following order:
   // a format name with neither dimension nor file, a format name with
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -42,18 +42,16 @@ class PluginDocument final : public Medi
 
   void SetScriptGlobalObject(
       nsIScriptGlobalObject* aScriptGlobalObject) override;
   bool CanSavePresentation(nsIRequest* aNewRequest) override;
 
   const nsCString& GetType() const { return mMimeType; }
   Element* GetPluginContent() { return mPluginContent; }
 
-  void StartLayout() { MediaDocument::StartLayout(); }
-
   virtual void Destroy() override {
     if (mStreamListener) {
       mStreamListener->DropDocumentRef();
     }
     MediaDocument::Destroy();
   }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
--- a/dom/html/VideoDocument.cpp
+++ b/dom/html/VideoDocument.cpp
@@ -33,22 +33,23 @@ class VideoDocument final : public Media
 
   virtual void Destroy() override {
     if (mStreamListener) {
       mStreamListener->DropDocumentRef();
     }
     MediaDocument::Destroy();
   }
 
+  nsresult StartLayout() override;
+
  protected:
+  nsresult CreateVideoElement();
   // Sets document <title> to reflect the file name and description.
   void UpdateTitle(nsIChannel* aChannel);
 
-  nsresult CreateSyntheticVideoDocument();
-
   RefPtr<MediaDocumentStreamListener> mStreamListener;
 };
 
 nsresult VideoDocument::StartDocumentLoad(const char* aCommand,
                                           nsIChannel* aChannel,
                                           nsILoadGroup* aLoadGroup,
                                           nsISupports* aContainer,
                                           nsIStreamListener** aDocListener,
@@ -57,47 +58,55 @@ nsresult VideoDocument::StartDocumentLoa
       aCommand, aChannel, aLoadGroup, aContainer, aDocListener, aReset, aSink);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mStreamListener = new MediaDocumentStreamListener(this);
   NS_ADDREF(*aDocListener = mStreamListener);
   return rv;
 }
 
+nsresult VideoDocument::StartLayout() {
+  // Create video element, and begin loading the media resource. Note we
+  // delay creating the video element until now (we're called from
+  // MediaDocumentStreamListener::OnStartRequest) as the PresShell is likely
+  // to have been created by now, so the MediaDecoder will be able to tell
+  // what kind of compositor we have, so the video element knows whether
+  // it can create a hardware accelerated video decoder or not.
+  nsresult rv = CreateVideoElement();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = MediaDocument::StartLayout();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 void VideoDocument::SetScriptGlobalObject(
     nsIScriptGlobalObject* aScriptGlobalObject) {
   // Set the script global object on the superclass before doing
   // anything that might require it....
   MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
 
   if (aScriptGlobalObject && !InitialSetupHasBeenDone()) {
-    // Create synthetic document
-#ifdef DEBUG
-    nsresult rv =
-#endif
-        CreateSyntheticVideoDocument();
+    DebugOnly<nsresult> rv = CreateSyntheticDocument();
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create synthetic video document");
 
     if (!nsContentUtils::IsChildOfSameType(this)) {
       LinkStylesheet(NS_LITERAL_STRING(
           "resource://content-accessible/TopLevelVideoDocument.css"));
       LinkStylesheet(NS_LITERAL_STRING(
           "chrome://global/skin/media/TopLevelVideoDocument.css"));
       LinkScript(NS_LITERAL_STRING(
           "chrome://global/content/TopLevelVideoDocument.js"));
     }
     InitialSetupDone();
   }
 }
 
-nsresult VideoDocument::CreateSyntheticVideoDocument() {
-  // make our generic document
-  nsresult rv = MediaDocument::CreateSyntheticDocument();
-  NS_ENSURE_SUCCESS(rv, rv);
-
+nsresult VideoDocument::CreateVideoElement() {
   Element* body = GetBodyElement();
   if (!body) {
     NS_WARNING("no body on video document!");
     return NS_ERROR_FAILURE;
   }
 
   // make content
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;