Bug 1151611 - Expose DXVA status in about:support. r=cpearce,felipe
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 28 Apr 2015 15:07:22 +1200
changeset 271211 7362533abe5ae0e90c87f58d28b4bb00655a3b6f
parent 271210 e3cb99d0589f36743f8b5fb34b120e94500a40a3
child 271212 fafcc7f4f663c2af3a9515d9cbff092f6af54db5
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, felipe
bugs1151611
milestone40.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 1151611 - Expose DXVA status in about:support. r=cpearce,felipe
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/media/fmp4/MP4Reader.cpp
dom/media/fmp4/MP4Reader.h
dom/media/fmp4/PlatformDecoderModule.cpp
dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
toolkit/locales/en-US/chrome/global/aboutSupport.properties
toolkit/modules/Troubleshoot.jsm
toolkit/modules/tests/browser/browser_Troubleshoot.js
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -20,16 +20,19 @@
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsFrame.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "ClientLayerManager.h"
 #include "nsQueryObject.h"
+#ifdef MOZ_FMP4
+#include "MP4Reader.h"
+#endif
 
 #include "nsIScrollableFrame.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsCharsetSource.h"
@@ -2232,16 +2235,37 @@ nsDOMWindowUtils::GetLayerManagerRemote(
   if (!mgr)
     return NS_ERROR_FAILURE;
 
   *retval = !!mgr->AsShadowForwarder();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::GetSupportsHardwareH264Decoding(bool* retval)
+{
+  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+
+#ifdef MOZ_FMP4
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
+  LayerManager *mgr = widget->GetLayerManager();
+  if (!mgr)
+    return NS_ERROR_FAILURE;
+
+  *retval = MP4Reader::IsVideoAccelerated(mgr->GetCompositorBackendType());
+#else
+  *retval = false;
+#endif
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   NS_ENSURE_ARG_POINTER(startIndex);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -46,17 +46,17 @@ interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(7ecfd6e7-120a-4567-85f7-14277f4c6d9f)]
+[scriptable, uuid(55d6b97f-0717-449d-ac6c-cdaba0a9b698)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1323,16 +1323,23 @@ interface nsIDOMWindowUtils : nsISupport
   /**
    * True if the layer manager for the widget associated with this window is
    * forwarding layers to a remote compositor, false otherwise. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute boolean layerManagerRemote;
 
   /**
+   * True if we can initialize a hardware-backed h264 decoder for a simple
+   * test video, does not mean that all h264 video decoding will be done
+   * in hardware.
+   */
+  readonly attribute boolean supportsHardwareH264Decoding;
+
+  /**
    * Record (and return) frame-intervals for frames which were presented
    *   between calling StartFrameTimeRecording and StopFrameTimeRecording.
    *
    * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late
    *     (elements were overwritten since Start), result is considered invalid and hence empty.
    * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent).
    *     Can be changed (up to 1 hour) via pref: toolkit.framesRecording.bufferSize.
    * - Note: the first frame-interval may be longer than expected because last frame
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -25,16 +25,17 @@
 #include <algorithm>
 
 #ifdef MOZ_EME
 #include "mozilla/CDMProxy.h"
 #endif
 
 using mozilla::layers::Image;
 using mozilla::layers::LayerManager;
+using mozilla::layers::ImageContainer;
 using mozilla::layers::LayersBackend;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetDemuxerLog() {
   static PRLogModuleInfo* log = nullptr;
   if (!log) {
     log = PR_NewLogModule("MP4Demuxer");
   }
@@ -65,16 +66,47 @@ TrackTypeToStr(TrackType aTrack)
   case kVideo:
     return "Video";
   default:
     return "Unknown";
   }
 }
 #endif
 
+uint8_t sTestExtraData[40] = { 0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
+                               0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96, 0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0 };
+
+/* static */ bool
+MP4Reader::IsVideoAccelerated(LayersBackend aBackend)
+{
+  VideoInfo config;
+  config.mMimeType = "video/avc";
+  config.mId = 1;
+  config.mDuration = 40000;
+  config.mMediaTime = 0;
+  config.mDisplay = config.mImage = nsIntSize(64, 64);
+  config.mExtraData = new MediaByteBuffer();
+  config.mExtraData->AppendElements(sTestExtraData, 40);
+
+  PlatformDecoderModule::Init();
+
+  nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
+
+  nsRefPtr<MediaDataDecoder> decoder =
+    platform->CreateDecoder(config, nullptr, nullptr, aBackend, nullptr);
+  nsresult rv = decoder->Init();
+  NS_ENSURE_SUCCESS(rv, false);
+
+  bool result = decoder->IsHardwareAccelerated();
+
+  decoder->Shutdown();
+
+  return result;
+}
+
 bool
 AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
 {
   SPSData spsdata;
   if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
                          (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
                          (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -83,16 +83,18 @@ public:
   virtual nsRefPtr<ShutdownPromise> Shutdown() override;
 
   virtual bool IsAsync() const override { return true; }
 
   virtual bool VideoIsHardwareAccelerated() const override;
 
   virtual void DisableHardwareAcceleration() override;
 
+  static bool IsVideoAccelerated(layers::LayersBackend aBackend);
+
 private:
 
   bool InitDemuxer();
   void ReturnOutput(MediaData* aData, TrackType aTrack);
 
   bool EnsureDecodersSetup();
 
   bool CheckIfDecoderSetup();
--- a/dom/media/fmp4/PlatformDecoderModule.cpp
+++ b/dom/media/fmp4/PlatformDecoderModule.cpp
@@ -113,18 +113,17 @@ PlatformDecoderModule::CreateCDMWrapper(
   return emepdm.forget();
 }
 #endif
 
 /* static */
 already_AddRefed<PlatformDecoderModule>
 PlatformDecoderModule::Create()
 {
-  // Note: This runs on the decode thread.
-  MOZ_ASSERT(!NS_IsMainThread());
+  // Note: This (usually) runs on the decode thread.
 
   nsRefPtr<PlatformDecoderModule> m(CreatePDM());
 
   if (m && NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
   return nullptr;
 }
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -49,18 +49,16 @@ GonkVideoDecoderManager::GonkVideoDecode
   const VideoInfo& aConfig)
   : GonkDecoderManager(aTaskQueue)
   , mImageContainer(aImageContainer)
   , mReaderCallback(nullptr)
   , mColorConverterBufferSize(0)
   , mNativeWindow(nullptr)
   , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock")
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
-  MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
   mMimeType = aConfig.mMimeType;
   mVideoWidth  = aConfig.mDisplay.width;
   mVideoHeight = aConfig.mDisplay.height;
   mDisplayWidth = aConfig.mDisplay.width;
   mDisplayHeight = aConfig.mDisplay.height;
   mInfo.mVideo = aConfig;
 
--- a/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -44,18 +44,22 @@ WMFMediaDataDecoder::Init()
   NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 nsresult
 WMFMediaDataDecoder::Shutdown()
 {
-  mTaskQueue->Dispatch(
-    NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
+  if (mTaskQueue) {
+    mTaskQueue->Dispatch(
+      NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
+  } else {
+    ProcessShutdown();
+  }
 #ifdef DEBUG
   {
     MonitorAutoLock mon(mMonitor);
     // The MP4Reader should have flushed before calling Shutdown().
     MOZ_ASSERT(!mIsDecodeTaskDispatched);
   }
 #endif
   return NS_OK;
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -73,18 +73,16 @@ WMFVideoMFTManager::WMFVideoMFTManager(
                             mozilla::layers::ImageContainer* aImageContainer,
                             bool aDXVAEnabled)
   : mImageContainer(aImageContainer)
   , mDXVAEnabled(aDXVAEnabled)
   , mLayersBackend(aLayersBackend)
   // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
   // Init().
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
-  MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(WMFVideoMFTManager);
 
   // Need additional checks/params to check vp8/vp9
   if (aConfig.mMimeType.EqualsLiteral("video/mp4") ||
       aConfig.mMimeType.EqualsLiteral("video/avc")) {
     mStreamType = H264;
   } else if (aConfig.mMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
     mStreamType = VP8;
@@ -160,17 +158,22 @@ WMFVideoMFTManager::InitializeDXVA()
       (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
        mLayersBackend != LayersBackend::LAYERS_D3D10 &&
        mLayersBackend != LayersBackend::LAYERS_D3D11)) {
     return false;
   }
 
   // The DXVA manager must be created on the main thread.
   nsRefPtr<CreateDXVAManagerEvent> event(new CreateDXVAManagerEvent(mLayersBackend));
-  NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+
+  if (NS_IsMainThread()) {
+    event->Run();
+  } else {
+    NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+  }
   mDXVA2Manager = event->mDXVA2Manager;
 
   return mDXVA2Manager != nullptr;
 }
 
 TemporaryRef<MFTDecoder>
 WMFVideoMFTManager::Init()
 {
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -32,16 +32,18 @@ pendingReports=All Crash Reports (includ
 # there are no good translations, these are only used in about:support
 
 # LOCALIZATION NOTE: This can be localized with a more generic term, like
 # "Graphics-accelerated Windows". It describes a number of windows, e.g.:
 # "GPU Accelerated Windows: 2/2 (Direct3D 9)"
 # "GPU Accelerated Windows: 0/2"
 acceleratedWindows = GPU Accelerated Windows
 
+supportsHardwareH264 = Supports Hardware H264 Decoding
+
 # LOCALIZATION NOTE (rawDataCopied) Text displayed in a mobile "Toast" to user when the
 # raw data is successfully copied to the clipboard via button press.
 rawDataCopied=Raw data copied to clipboard
 
 # LOCALIZATION NOTE (textCopied) Text displayed in a mobile "Toast" to user when the
 # text is successfully copied to the clipboard via button press.
 textCopied=Text copied to clipboard
 
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -308,16 +308,17 @@ let dataProviders = {
     while (winEnumer.hasMoreElements()) {
       data.numTotalWindows++;
       let winUtils = winEnumer.getNext().
                      QueryInterface(Ci.nsIInterfaceRequestor).
                      getInterface(Ci.nsIDOMWindowUtils);
       try {
         data.windowLayerManagerType = winUtils.layerManagerType;
         data.windowLayerManagerRemote = winUtils.layerManagerRemote;
+        data.supportsHardwareH264 = winUtils.supportsHardwareH264Decoding;
       }
       catch (e) {
         continue;
       }
       if (data.windowLayerManagerType != "Basic")
         data.numAcceleratedWindows++;
     }
 
--- a/toolkit/modules/tests/browser/browser_Troubleshoot.js
+++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js
@@ -194,16 +194,19 @@ const SNAPSHOT_SCHEMA = {
           type: "number",
         },
         windowLayerManagerType: {
           type: "string",
         },
         windowLayerManagerRemote: {
           type: "boolean",
         },
+        supportsHardwareH264: {
+          type: "boolean",
+        },
         numAcceleratedWindowsMessage: {
           type: "array",
         },
         adapterDescription: {
           type: "string",
         },
         adapterVendorID: {
           type: "string",