Bug 1540581 - P12. Pass YUV colorspace information with WMF decoder. r=bryce,mattwoodrow.
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 11 Apr 2019 12:38:51 +0000
changeset 527957 a0176a275ee5a60ce1bef7bde28055cc49cc2a26
parent 527956 bfef6e9e74d53eaa3ef44f27498f31c2b5aee34f
child 527958 575c1e8291c7e3c6c2a3b7160a7b862b304520cc
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbryce, mattwoodrow
bugs1540581
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 1540581 - P12. Pass YUV colorspace information with WMF decoder. r=bryce,mattwoodrow. Differential Revision: https://phabricator.services.mozilla.com/D26467
dom/media/platforms/wmf/DXVA2Manager.cpp
dom/media/platforms/wmf/DXVA2Manager.h
dom/media/platforms/wmf/WMFVideoMFTManager.cpp
dom/media/platforms/wmf/WMFVideoMFTManager.h
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -1,36 +1,37 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "DXVA2Manager.h"
 #include <d3d11.h>
-#include "DXVA2Manager.h"
 #include "D3D9SurfaceImage.h"
 #include "DriverCrashGuard.h"
 #include "GfxDriverInfo.h"
 #include "ImageContainer.h"
 #include "MFTDecoder.h"
 #include "MediaTelemetryConstants.h"
+#include "VideoUtils.h"
+#include "WMFUtils.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxPrefs.h"
 #include "gfxWindowsPlatform.h"
 #include "mfapi.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/gfx/DeviceManagerDx.h"
 #include "mozilla/layers/D3D11ShareHandleImage.h"
 #include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/TextureD3D11.h"
 #include "mozilla/layers/TextureForwarder.h"
-#include "mozilla/layers/TextureD3D11.h"
+#include "mozilla/mscom/EnsureMTA.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
-#include "VideoUtils.h"
-#include "mozilla/mscom/EnsureMTA.h"
 
 const CLSID CLSID_VideoProcessorMFT = {
     0x88753b26,
     0x5b24,
     0x49bd,
     {0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82}};
 
 const GUID MF_XVP_PLAYBACK_MODE = {
@@ -586,17 +587,18 @@ class D3D11DXVA2Manager : public DXVA2Ma
   // Copies a region (aRegion) of the video frame stored in aVideoSample
   // into an image which is returned by aOutImage.
   HRESULT CopyToImage(IMFSample* aVideoSample, const gfx::IntRect& aRegion,
                       Image** aOutImage) override;
 
   HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture, const GUID& aSubType,
                             ID3D11Texture2D** aOutTexture) override;
 
-  HRESULT ConfigureForSize(IMFMediaType* aInputType, uint32_t aWidth,
+  HRESULT ConfigureForSize(IMFMediaType* aInputType,
+                           gfx::YUVColorSpace aColorSpace, uint32_t aWidth,
                            uint32_t aHeight) override;
 
   bool IsD3D11() override { return true; }
 
   bool SupportsConfig(IMFMediaType* aType, float aFramerate) override;
 
  private:
   HRESULT CreateFormatConverter();
@@ -618,16 +620,17 @@ class D3D11DXVA2Manager : public DXVA2Ma
   RefPtr<ID3D11VideoDecoder> mDecoder;
   RefPtr<layers::SyncObjectClient> mSyncObject;
   GUID mDecoderGUID;
   uint32_t mWidth = 0;
   uint32_t mHeight = 0;
   UINT mDeviceManagerToken = 0;
   RefPtr<IMFMediaType> mInputType;
   GUID mInputSubType;
+  gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::BT601;
 };
 
 bool D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate) {
   MOZ_ASSERT(NS_IsMainThread());
   D3D11_VIDEO_DECODER_DESC desc;
   desc.Guid = mDecoderGUID;
   desc.OutputFormat = DXGI_FORMAT_NV12;
   HRESULT hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &desc.SampleWidth,
@@ -877,19 +880,18 @@ D3D11DXVA2Manager::CreateOutputSample(Re
 
 HRESULT
 D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
                                const gfx::IntRect& aRegion, Image** aOutImage) {
   NS_ENSURE_TRUE(aVideoSample, E_POINTER);
   NS_ENSURE_TRUE(aOutImage, E_POINTER);
   MOZ_ASSERT(mTextureClientAllocator);
 
-  RefPtr<D3D11ShareHandleImage> image =
-      new D3D11ShareHandleImage(gfx::IntSize(mWidth, mHeight), aRegion,
-                                mInputSubType, gfx::YUVColorSpace::UNKNOWN);
+  RefPtr<D3D11ShareHandleImage> image = new D3D11ShareHandleImage(
+      gfx::IntSize(mWidth, mHeight), aRegion, mInputSubType, mYUVColorSpace);
 
   // Retrieve the DXGI_FORMAT for the current video sample.
   RefPtr<IMFMediaBuffer> buffer;
   HRESULT hr = aVideoSample->GetBufferByIndex(0, getter_AddRefs(buffer));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   RefPtr<IMFDXGIBuffer> dxgiBuf;
   hr = buffer->QueryInterface((IMFDXGIBuffer**)getter_AddRefs(dxgiBuf));
@@ -998,17 +1000,17 @@ D3D11DXVA2Manager::CopyToBGRATexture(ID3
 
     hr = inputType->SetUINT32(MF_MT_INTERLACE_MODE,
                               MFVideoInterlace_Progressive);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
     hr = inputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-    hr = ConfigureForSize(inputType, desc.Width, desc.Height);
+    hr = ConfigureForSize(inputType, mYUVColorSpace, desc.Width, desc.Height);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   }
 
   RefPtr<IDXGIKeyedMutex> mutex;
   inTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
   // The rest of this function will not work if inTexture implements
   // IDXGIKeyedMutex! In that case case we would have to copy to a
   // non-mutex using texture.
@@ -1063,23 +1065,25 @@ D3D11DXVA2Manager::CopyToBGRATexture(ID3
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   texture.forget(aOutTexture);
 
   return S_OK;
 }
 
 HRESULT
-D3D11DXVA2Manager::ConfigureForSize(IMFMediaType* aInputType, uint32_t aWidth,
-                                    uint32_t aHeight) {
+D3D11DXVA2Manager::ConfigureForSize(IMFMediaType* aInputType,
+                                    gfx::YUVColorSpace aColorSpace,
+                                    uint32_t aWidth, uint32_t aHeight) {
   GUID subType = {0};
   HRESULT hr = aInputType->GetGUID(MF_MT_SUBTYPE, &subType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  if (subType == mInputSubType && aWidth == mWidth && aHeight == mHeight) {
+  if (subType == mInputSubType && aWidth == mWidth && aHeight == mHeight &&
+      mYUVColorSpace == aColorSpace) {
     // If the media type hasn't changed, don't reconfigure.
     return S_OK;
   }
 
   // Create a copy of our input type.
   RefPtr<IMFMediaType> inputType;
   hr = wmf::MFCreateMediaType(getter_AddRefs(inputType));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
@@ -1126,17 +1130,17 @@ D3D11DXVA2Manager::ConfigureForSize(IMFM
         });
   });
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   mWidth = aWidth;
   mHeight = aHeight;
   mInputType = inputType;
   mInputSubType = subType;
-
+  mYUVColorSpace = aColorSpace;
   return S_OK;
 }
 
 bool D3D11DXVA2Manager::CanCreateDecoder(const D3D11_VIDEO_DECODER_DESC& aDesc,
                                          const float aFramerate) const {
   MOZ_ASSERT(NS_IsMainThread());
   if (IsUnsupportedResolution(aDesc.SampleWidth, aDesc.SampleHeight,
                               aFramerate)) {
--- a/dom/media/platforms/wmf/DXVA2Manager.h
+++ b/dom/media/platforms/wmf/DXVA2Manager.h
@@ -45,18 +45,19 @@ class DXVA2Manager {
   virtual HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture,
                                     const GUID& aSubType,
                                     ID3D11Texture2D** aOutTexture) {
     // Not implemented!
     MOZ_CRASH("CopyToBGRATexture not implemented on this manager.");
     return E_FAIL;
   }
 
-  virtual HRESULT ConfigureForSize(IMFMediaType* aInputType, uint32_t aWidth,
-                                   uint32_t aHeight) {
+  virtual HRESULT ConfigureForSize(IMFMediaType* aInputType,
+                                   gfx::YUVColorSpace aColorSpace,
+                                   uint32_t aWidth, uint32_t aHeight) {
     return S_OK;
   }
 
   virtual bool IsD3D11() { return false; }
 
   virtual ~DXVA2Manager();
 
   virtual bool SupportsConfig(IMFMediaType* aType, float aFramerate) = 0;
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -131,17 +131,19 @@ LayersBackend GetCompositorBackendType(
 WMFVideoMFTManager::WMFVideoMFTManager(
     const VideoInfo& aConfig, layers::KnowsCompositor* aKnowsCompositor,
     layers::ImageContainer* aImageContainer, float aFramerate,
     const CreateDecoderParams::OptionSet& aOptions, bool aDXVAEnabled)
     : mVideoInfo(aConfig),
       mImageSize(aConfig.mImage),
       mDecodedImageSize(aConfig.mImage),
       mVideoStride(0),
-      mYUVColorSpace(YUVColorSpace::BT601),
+      mColorSpace(aConfig.mColorSpace != gfx::YUVColorSpace::UNKNOWN
+                      ? Some(aConfig.mColorSpace)
+                      : Nothing()),
       mImageContainer(aImageContainer),
       mKnowsCompositor(aKnowsCompositor),
       mDXVAEnabled(aDXVAEnabled &&
                    !aOptions.contains(
                        CreateDecoderParams::Option::HardwareDecoderNotAllowed)),
       mFramerate(aFramerate),
       mLowLatency(aOptions.contains(CreateDecoderParams::Option::LowLatency))
 // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
@@ -652,25 +654,24 @@ MediaResult WMFVideoMFTManager::InitInte
     // re-do initialization.
     return InitInternal();
   }
 
   LOG("Video Decoder initialized, Using DXVA: %s",
       (mUseHwAccel ? "Yes" : "No"));
 
   if (mUseHwAccel) {
-    hr = mDXVA2Manager->ConfigureForSize(outputType,
-                                         mVideoInfo.ImageRect().width,
-                                         mVideoInfo.ImageRect().height);
+    hr = mDXVA2Manager->ConfigureForSize(
+        outputType, mColorSpace.refOr(gfx::YUVColorSpace::BT601),
+        mVideoInfo.ImageRect().width, mVideoInfo.ImageRect().height);
     NS_ENSURE_TRUE(SUCCEEDED(hr),
                    MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                                RESULT_DETAIL("Fail to configure image size for "
                                              "DXVA2Manager.")));
   } else {
-    mYUVColorSpace = GetYUVColorSpace(outputType);
     GetDefaultStride(outputType, mVideoInfo.ImageRect().width, &mVideoStride);
   }
   LOG("WMFVideoMFTManager frame geometry stride=%u picture=(%d, %d, %d, %d) "
       "display=(%d,%d)",
       mVideoStride, mVideoInfo.ImageRect().x, mVideoInfo.ImageRect().y,
       mVideoInfo.ImageRect().width, mVideoInfo.ImageRect().height,
       mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height);
 
@@ -750,16 +751,22 @@ WMFVideoMFTManager::Input(MediaRawData* 
 
   RefPtr<IMFSample> inputSample;
   HRESULT hr = mDecoder->CreateInputSample(
       aSample->Data(), uint32_t(aSample->Size()),
       aSample->mTime.ToMicroseconds(), aSample->mDuration.ToMicroseconds(),
       &inputSample);
   NS_ENSURE_TRUE(SUCCEEDED(hr) && inputSample != nullptr, hr);
 
+  if (!mColorSpace && aSample->mTrackInfo) {
+    // The colorspace definition is found in the H264 SPS NAL, available out of
+    // band, while for VP9 it's only available within the VP9 bytestream.
+    // The info would have been updated by the MediaChangeMonitor.
+    mColorSpace = Some(aSample->mTrackInfo->GetAsVideoInfo()->mColorSpace);
+  }
   mLastDuration = aSample->mDuration;
 
   // Forward sample data to the decoder.
   return mDecoder->Input(inputSample);
 }
 
 class SupportsConfigEvent : public Runnable {
  public:
@@ -917,17 +924,17 @@ WMFVideoMFTManager::CreateBasicVideoFram
     b.mPlanes[2].mStride = stride;
     b.mPlanes[2].mHeight = halfHeight;
     b.mPlanes[2].mWidth = halfWidth;
     b.mPlanes[2].mOffset = 0;
     b.mPlanes[2].mSkip = 1;
   }
 
   // YuvColorSpace
-  b.mYUVColorSpace = mYUVColorSpace;
+  b.mYUVColorSpace = *mColorSpace;
   b.mColorDepth = colorDepth;
 
   TimeUnit pts = GetSampleTime(aSample);
   NS_ENSURE_TRUE(pts.IsValid(), E_FAIL);
   TimeUnit duration = GetSampleDuration(aSample);
   NS_ENSURE_TRUE(duration.IsValid(), E_FAIL);
   gfx::IntRect pictureRegion =
       mVideoInfo.ScaledImageRect(videoWidth, videoHeight);
@@ -1029,23 +1036,22 @@ WMFVideoMFTManager::Output(int64_t aStre
         return hr;
       }
 
       RefPtr<IMFMediaType> outputType;
       hr = mDecoder->GetOutputMediaType(outputType);
       NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
       if (mUseHwAccel) {
-        hr = mDXVA2Manager->ConfigureForSize(outputType,
-                                             mVideoInfo.ImageRect().width,
-                                             mVideoInfo.ImageRect().height);
+        hr = mDXVA2Manager->ConfigureForSize(
+            outputType, mColorSpace.refOr(gfx::YUVColorSpace::BT601),
+            mVideoInfo.ImageRect().width, mVideoInfo.ImageRect().height);
         NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
       } else {
         // The stride may have changed, recheck for it.
-        mYUVColorSpace = GetYUVColorSpace(outputType);
         hr = GetDefaultStride(outputType, mVideoInfo.ImageRect().width,
                               &mVideoStride);
         NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
         UINT32 width = 0, height = 0;
         hr = MFGetAttributeSize(outputType, MF_MT_FRAME_SIZE, &width, &height);
         NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
         NS_ENSURE_TRUE(width <= MAX_VIDEO_WIDTH, E_FAIL);
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.h
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h
@@ -66,17 +66,17 @@ class WMFVideoMFTManager : public MFTMan
 
   bool CanUseDXVA(IMFMediaType* aType, float aFramerate);
 
   // Video frame geometry.
   const VideoInfo mVideoInfo;
   const gfx::IntSize mImageSize;
   gfx::IntSize mDecodedImageSize;
   uint32_t mVideoStride;
-  gfx::YUVColorSpace mYUVColorSpace;
+  Maybe<gfx::YUVColorSpace> mColorSpace;
 
   RefPtr<layers::ImageContainer> mImageContainer;
   RefPtr<layers::KnowsCompositor> mKnowsCompositor;
   nsAutoPtr<DXVA2Manager> mDXVA2Manager;
 
   media::TimeUnit mLastDuration;
 
   bool mDXVAEnabled;