Bug 1495025 - P3. Store original IMFMediaType's subtype in D3D11SharedHandleImage. r=cpearce
☠☠ backed out by 9f2c6ae03c6d ☠ ☠
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 04 Oct 2018 09:40:51 +0000
changeset 495655 7fd1f610329421e1eda758168874348797b6a502
parent 495654 f1afe7e2a9e31c7806f2eff9193e79e6a201b8c9
child 495656 9f59a50dcc6df39df6ffa184148a6dd1c1c42295
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1495025
milestone64.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 1495025 - P3. Store original IMFMediaType's subtype in D3D11SharedHandleImage. r=cpearce This allows more easily the creation of the MFT required to convert to a RGBA32 image when doing a readback. Depends on D7295 Differential Revision: https://phabricator.services.mozilla.com/D7296
dom/media/platforms/wmf/DXVA2Manager.cpp
dom/media/platforms/wmf/DXVA2Manager.h
gfx/layers/D3D11ShareHandleImage.cpp
gfx/layers/D3D11ShareHandleImage.h
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -615,18 +615,19 @@ public:
   IUnknown* GetDXVADeviceManager() override;
 
   // 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;
 
-  virtual HRESULT CopyToBGRATexture(ID3D11Texture2D *aInTexture,
-                                    ID3D11Texture2D** aOutTexture);
+  HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture,
+                            const GUID& aSubType,
+                            ID3D11Texture2D** aOutTexture) override;
 
   HRESULT ConfigureForSize(IMFMediaType* aInputType) override;
 
   bool IsD3D11() override { return true; }
 
   bool SupportsConfig(IMFMediaType* aType, float aFramerate) override;
 
 private:
@@ -648,16 +649,17 @@ private:
   RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
   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;
 };
 
 bool
 D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate)
 {
   MOZ_ASSERT(NS_IsMainThread());
   D3D11_VIDEO_DECODER_DESC desc;
   desc.Guid = mDecoderGUID;
@@ -914,59 +916,60 @@ 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);
+  RefPtr<D3D11ShareHandleImage> image = new D3D11ShareHandleImage(
+    gfx::IntSize(mWidth, mHeight), aRegion, mInputSubType);
 
   // 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));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   RefPtr<ID3D11Texture2D> tex;
   hr = dxgiBuf->GetResource(__uuidof(ID3D11Texture2D), getter_AddRefs(tex));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  D3D11_TEXTURE2D_DESC desc;
-  tex->GetDesc(&desc);
+  D3D11_TEXTURE2D_DESC inDesc;
+  tex->GetDesc(&inDesc);
 
-  bool ok = image->AllocateTexture(
-    mTextureClientAllocator, mDevice, desc.Format == DXGI_FORMAT_NV12);
+  bool ok = image->AllocateTexture(mTextureClientAllocator, mDevice);
   NS_ENSURE_TRUE(ok, E_FAIL);
 
   RefPtr<TextureClient> client =
     image->GetTextureClient(ImageBridgeChild::GetSingleton().get());
   NS_ENSURE_TRUE(client, E_FAIL);
 
+  RefPtr<ID3D11Texture2D> texture = image->GetTexture();
+  D3D11_TEXTURE2D_DESC outDesc;
+  texture->GetDesc(&outDesc);
+
   RefPtr<IDXGIKeyedMutex> mutex;
-  RefPtr<ID3D11Texture2D> texture = image->GetTexture();
-
   texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
 
   {
     AutoTextureLock(mutex, hr, 2000);
     if (mutex && (FAILED(hr) || hr == WAIT_TIMEOUT || hr == WAIT_ABANDONED)) {
       return hr;
     }
 
     if (!mutex && mDevice != DeviceManagerDx::Get()->GetCompositorDevice()) {
       NS_ENSURE_TRUE(mSyncObject, E_FAIL);
     }
 
-    if (client && client->GetFormat() == SurfaceFormat::NV12) {
+    if (outDesc.Format == inDesc.Format) {
       // Our video frame is stored in a non-sharable ID3D11Texture2D. We need
       // to create a copy of that frame as a sharable resource, save its share
       // handle, and put that handle into the rendering pipeline.
 
       UINT index;
       dxgiBuf->GetSubresourceIndex(&index);
       mContext->CopySubresourceRegion(texture, 0, 0, 0, 0, tex, index, nullptr);
     } else {
@@ -996,33 +999,19 @@ D3D11DXVA2Manager::CopyToImage(IMFSample
     }
   }
 
   image.forget(aOutImage);
 
   return S_OK;
 }
 
-const GUID& TextureFormatToSubType(DXGI_FORMAT aFormat)
-{
-  switch (aFormat) {
-    case DXGI_FORMAT_NV12:
-      return MFVideoFormat_NV12;
-    case DXGI_FORMAT_P010:
-      return MFVideoFormat_P010;
-    case DXGI_FORMAT_P016:
-      return MFVideoFormat_P016;
-    default:
-      // TextureFormat not handled.
-      return MFVideoFormat_NV12;
-  }
-}
-
 HRESULT
-D3D11DXVA2Manager::CopyToBGRATexture(ID3D11Texture2D *aInTexture,
+D3D11DXVA2Manager::CopyToBGRATexture(ID3D11Texture2D* aInTexture,
+                                     const GUID& aSubType,
                                      ID3D11Texture2D** aOutTexture)
 {
   NS_ENSURE_TRUE(aInTexture, E_POINTER);
   NS_ENSURE_TRUE(aOutTexture, E_POINTER);
 
   HRESULT hr;
   RefPtr<ID3D11Texture2D> texture, inTexture;
 
@@ -1034,17 +1023,17 @@ D3D11DXVA2Manager::CopyToBGRATexture(ID3
   if (!mInputType || desc.Width != mWidth || desc.Height != mHeight) {
     RefPtr<IMFMediaType> inputType;
     hr = wmf::MFCreateMediaType(getter_AddRefs(inputType));
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
     hr = inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-    hr = inputType->SetGUID(MF_MT_SUBTYPE, TextureFormatToSubType(desc.Format));
+    hr = inputType->SetGUID(MF_MT_SUBTYPE, aSubType);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
     hr =
       MFSetAttributeSize(inputType, MF_MT_FRAME_SIZE, desc.Width, desc.Height);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
     hr =
       inputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
@@ -1127,16 +1116,20 @@ D3D11DXVA2Manager::ConfigureForSize(IMFM
   }
 
   UINT32 width = 0, height = 0;
   HRESULT hr = MFGetAttributeSize(aInputType, MF_MT_FRAME_SIZE, &width, &height);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   mWidth = width;
   mHeight = height;
 
+  GUID subType = { 0 };
+  hr = aInputType->GetGUID(MF_MT_SUBTYPE, &subType);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
   RefPtr<IMFAttributes> attr;
   mozilla::mscom::EnsureMTA(
     [&]() -> void { attr = mTransform->GetAttributes(); });
   NS_ENSURE_TRUE(attr != nullptr, E_FAIL);
 
   hr = attr->SetUINT32(MF_XVP_PLAYBACK_MODE, TRUE);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
@@ -1166,16 +1159,17 @@ D3D11DXVA2Manager::ConfigureForSize(IMFM
         NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
         return S_OK;
       });
   });
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   mInputType = aInputType;
+  mInputSubType = subType;
 
   return S_OK;
 }
 
 bool
 D3D11DXVA2Manager::CanCreateDecoder(const D3D11_VIDEO_DECODER_DESC& aDesc,
                                     const float aFramerate) const
 {
--- a/dom/media/platforms/wmf/DXVA2Manager.h
+++ b/dom/media/platforms/wmf/DXVA2Manager.h
@@ -41,17 +41,18 @@ public:
   // IMFDXGIDeviceManager. It is safe to call this on any thread.
   virtual IUnknown* GetDXVADeviceManager() = 0;
 
   // Creates an Image for the video frame stored in aVideoSample.
   virtual HRESULT CopyToImage(IMFSample* aVideoSample,
                               const gfx::IntRect& aRegion,
                               layers::Image** aOutImage) = 0;
 
-  virtual HRESULT CopyToBGRATexture(ID3D11Texture2D *aInTexture,
+  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)
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -19,30 +19,33 @@
 #include <memory>
 
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 D3D11ShareHandleImage::D3D11ShareHandleImage(const gfx::IntSize& aSize,
-                                             const gfx::IntRect& aRect)
- : Image(nullptr, ImageFormat::D3D11_SHARE_HANDLE_TEXTURE),
-   mSize(aSize),
-   mPictureRect(aRect)
+                                             const gfx::IntRect& aRect,
+                                             const GUID& aSourceFormat)
+  : Image(nullptr, ImageFormat::D3D11_SHARE_HANDLE_TEXTURE)
+  , mSize(aSize)
+  , mPictureRect(aRect)
+  , mSourceFormat(aSourceFormat)
+
 {
 }
 
 bool
 D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator,
-                                       ID3D11Device* aDevice,
-                                       bool aPreferNV12)
+                                       ID3D11Device* aDevice)
 {
   if (aAllocator) {
-    if (aPreferNV12 && gfxPrefs::PDMWMFUseNV12Format() &&
+    if (mSourceFormat == MFVideoFormat_NV12 &&
+        gfxPrefs::PDMWMFUseNV12Format() &&
         gfx::DeviceManagerDx::Get()->CanUseNV12()) {
       mTextureClient =
         aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::NV12, mSize);
     } else {
       mTextureClient =
         aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
     }
     if (mTextureClient) {
@@ -97,20 +100,21 @@ D3D11ShareHandleImage::GetAsSourceSurfac
 
     if (!manager) {
       gfxWarning() << "Failed to create DXVA2 manager!";
       return nullptr;
     }
 
     RefPtr<ID3D11Texture2D> outTexture;
 
-    hr = manager->CopyToBGRATexture(texture, getter_AddRefs(outTexture));
+    hr = manager->CopyToBGRATexture(
+      texture, mSourceFormat, getter_AddRefs(outTexture));
 
     if (FAILED(hr)) {
-      gfxWarning() << "Failed to copy NV12 to BGRA texture.";
+      gfxWarning() << "Failed to copy to BGRA texture.";
       return nullptr;
     }
 
     texture = outTexture;
     texture->GetDesc(&desc);
   }
 
   CD3D11_TEXTURE2D_DESC softDesc(desc.Format, desc.Width, desc.Height);
--- a/gfx/layers/D3D11ShareHandleImage.h
+++ b/gfx/layers/D3D11ShareHandleImage.h
@@ -47,33 +47,34 @@ protected:
 
 // Image class that wraps a ID3D11Texture2D. This class copies the image
 // passed into SetData(), so that it can be accessed from other D3D devices.
 // This class also manages the synchronization of the copy, to ensure the
 // resource is ready to use.
 class D3D11ShareHandleImage final : public Image {
 public:
   D3D11ShareHandleImage(const gfx::IntSize& aSize,
-                        const gfx::IntRect& aRect);
+                        const gfx::IntRect& aRect,
+                        const GUID& aSourceFormat);
   virtual ~D3D11ShareHandleImage() {}
 
   bool AllocateTexture(D3D11RecycleAllocator* aAllocator,
-                       ID3D11Device* aDevice,
-                       bool aPreferNV12);
+                       ID3D11Device* aDevice);
 
   gfx::IntSize GetSize() const override;
   already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
   TextureClient* GetTextureClient(KnowsCompositor* aForwarder) override;
   gfx::IntRect GetPictureRect() const override { return mPictureRect; }
 
   ID3D11Texture2D* GetTexture() const;
 
 private:
   gfx::IntSize mSize;
   gfx::IntRect mPictureRect;
+  const GUID mSourceFormat;
   RefPtr<TextureClient> mTextureClient;
   RefPtr<ID3D11Texture2D> mTexture;
 };
 
 } // namepace layers
 } // namespace mozilla
 
 #endif // GFX_D3DSURFACEIMAGE_H