Bug 1178098 - Report why DXVA initialization failed to about:support. r=cpearce

This commit is contained in:
Matt Woodrow 2015-07-13 16:12:23 -04:00
parent 9b3c25dbd1
commit ca36359af3
19 changed files with 117 additions and 54 deletions

View File

@ -2261,7 +2261,7 @@ nsDOMWindowUtils::GetLayerManagerRemote(bool* retval)
}
NS_IMETHODIMP
nsDOMWindowUtils::GetSupportsHardwareH264Decoding(bool* retval)
nsDOMWindowUtils::GetSupportsHardwareH264Decoding(nsAString& aRetval)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
@ -2274,9 +2274,15 @@ nsDOMWindowUtils::GetSupportsHardwareH264Decoding(bool* retval)
if (!mgr)
return NS_ERROR_FAILURE;
*retval = MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType());
nsCString failureReason;
if (MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), failureReason)) {
aRetval.AssignLiteral("Yes");
} else {
aRetval.AssignLiteral("No; ");
AppendUTF8toUTF16(failureReason, aRetval);
}
#else
*retval = false;
aRetval.AssignLiteral("No; Compiled without MP4 support.");
#endif
return NS_OK;
}

View File

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(6064615a-a782-4d08-86db-26ef3851208a)]
[scriptable, uuid(47fa312b-2ad1-4b80-8a0a-c9822e2d1ec9)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1342,7 +1342,7 @@ interface nsIDOMWindowUtils : nsISupports {
* test video, does not mean that all h264 video decoding will be done
* in hardware.
*/
readonly attribute boolean supportsHardwareH264Decoding;
readonly attribute AString supportsHardwareH264Decoding;
/**
* Record (and return) frame-intervals for frames which were presented

View File

@ -1114,8 +1114,9 @@ MediaFormatReader::Update(TrackType aTrack)
if (!decoder.mOutput.IsEmpty()) {
// We have a decoded sample ready to be returned.
if (aTrack == TrackType::kVideoTrack) {
nsCString error;
mVideo.mIsHardwareAccelerated =
mVideo.mDecoder && mVideo.mDecoder->IsHardwareAccelerated();
mVideo.mDecoder && mVideo.mDecoder->IsHardwareAccelerated(error);
}
while (decoder.mOutput.Length()) {
nsRefPtr<MediaData> output = decoder.mOutput[0];

View File

@ -283,14 +283,15 @@ CreateTestH264Decoder(layers::LayersBackend aBackend,
}
/* static */ bool
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend)
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aFailureReason)
{
VideoInfo config;
nsRefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config));
if (!decoder) {
aFailureReason.AssignLiteral("Failed to create H264 decoder");
return false;
}
bool result = decoder->IsHardwareAccelerated();
bool result = decoder->IsHardwareAccelerated(aFailureReason);
return result;
}

View File

@ -42,7 +42,7 @@ public:
// Returns true if the MP4 backend is preffed on.
static bool IsEnabled();
static bool IsVideoAccelerated(layers::LayersBackend aBackend);
static bool IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aReason);
static bool CanCreateAACDecoder();
static bool CanCreateH264Decoder();
};

View File

@ -263,7 +263,7 @@ public:
// Called from the state machine task queue or main thread.
// Decoder needs to decide whether or not hardware accelearation is supported
// after creating. It doesn't need to call Init() before calling this function.
virtual bool IsHardwareAccelerated() const { return false; }
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
// ConfigurationChanged will be called to inform the video or audio decoder
// that the format of the next input sample is about to change.

View File

@ -299,9 +299,9 @@ SharedDecoderProxy::Shutdown()
}
bool
SharedDecoderProxy::IsHardwareAccelerated() const
SharedDecoderProxy::IsHardwareAccelerated(nsACString& aFailureReason) const
{
return mManager->mDecoder->IsHardwareAccelerated();
return mManager->mDecoder->IsHardwareAccelerated(aFailureReason);
}
} // namespace mozilla

View File

@ -79,7 +79,7 @@ public:
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsHardwareAccelerated() const override;
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
friend class SharedDecoderManager;

View File

@ -76,7 +76,7 @@ public:
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsHardwareAccelerated() const override
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override
{
return true;
}

View File

@ -22,7 +22,7 @@ public:
virtual ~AppleVTDecoder();
virtual nsRefPtr<InitPromise> Init() override;
virtual nsresult Input(MediaRawData* aSample) override;
virtual bool IsHardwareAccelerated() const override
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override
{
return mIsHardwareAccelerated;
}

View File

@ -16,6 +16,7 @@
#include "mfapi.h"
#include "MFTDecoder.h"
#include "DriverCrashGuard.h"
#include "nsPrintfCString.h"
const CLSID CLSID_VideoProcessorMFT =
{
@ -50,7 +51,7 @@ public:
D3D9DXVA2Manager();
virtual ~D3D9DXVA2Manager();
HRESULT Init();
HRESULT Init(nsACString& aFailureReason);
IUnknown* GetDXVADeviceManager() override;
@ -90,13 +91,14 @@ D3D9DXVA2Manager::GetDXVADeviceManager()
}
HRESULT
D3D9DXVA2Manager::Init()
D3D9DXVA2Manager::Init(nsACString& aFailureReason)
{
MOZ_ASSERT(NS_IsMainThread());
gfx::D3D9VideoCrashGuard crashGuard;
if (crashGuard.Crashed()) {
NS_WARNING("DXVA2D3D9 crash detected");
aFailureReason.AssignLiteral("DXVA2D3D9 crashes detected in the past");
return E_FAIL;
}
@ -109,6 +111,7 @@ D3D9DXVA2Manager::Init()
HRESULT hr = d3d9Create(D3D_SDK_VERSION, getter_AddRefs(d3d9Ex));
if (!d3d9Ex) {
NS_WARNING("Direct3DCreate9 failed");
aFailureReason.AssignLiteral("Direct3DCreate9 failed");
return E_FAIL;
}
@ -118,7 +121,10 @@ D3D9DXVA2Manager::Init()
D3DDEVTYPE_HAL,
(D3DFORMAT)MAKEFOURCC('N','V','1','2'),
D3DFMT_X8R8G8B8);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("CheckDeviceFormatConversion failed with error %X", hr);
return hr;
}
// Create D3D9DeviceEx.
D3DPRESENT_PARAMETERS params = {0};
@ -141,7 +147,10 @@ D3D9DXVA2Manager::Init()
&params,
nullptr,
getter_AddRefs(device));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("CreateDeviceEx failed with error %X", hr);
return hr;
}
// Ensure we can create queries to synchronize operations between devices.
// Without this, when we make a copy of the frame in order to share it with
@ -150,7 +159,10 @@ D3D9DXVA2Manager::Init()
nsRefPtr<IDirect3DQuery9> query;
hr = device->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("CreateQuery failed with error %X", hr);
return hr;
}
// Create and initialize IDirect3DDeviceManager9.
UINT resetToken = 0;
@ -158,9 +170,15 @@ D3D9DXVA2Manager::Init()
hr = wmf::DXVA2CreateDirect3DDeviceManager9(&resetToken,
getter_AddRefs(deviceManager));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("DXVA2CreateDirect3DDeviceManager9 failed with error %X", hr);
return hr;
}
hr = deviceManager->ResetDevice(device, resetToken);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("IDirect3DDeviceManager9::ResetDevice failed with error %X", hr);
return hr;
}
mResetToken = resetToken;
mD3D9 = d3d9Ex;
@ -210,7 +228,7 @@ static uint32_t sDXVAVideosCount = 0;
/* static */
DXVA2Manager*
DXVA2Manager::CreateD3D9DXVA()
DXVA2Manager::CreateD3D9DXVA(nsACString& aFailureReason)
{
MOZ_ASSERT(NS_IsMainThread());
HRESULT hr;
@ -220,11 +238,12 @@ DXVA2Manager::CreateD3D9DXVA()
const uint32_t dxvaLimit =
Preferences::GetInt("media.windows-media-foundation.max-dxva-videos", 8);
if (sDXVAVideosCount == dxvaLimit) {
aFailureReason.AssignLiteral("Too many DXVA videos playing");
return nullptr;
}
nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager());
hr = d3d9Manager->Init();
hr = d3d9Manager->Init(aFailureReason);
if (SUCCEEDED(hr)) {
return d3d9Manager.forget();
}
@ -239,7 +258,7 @@ public:
D3D11DXVA2Manager();
virtual ~D3D11DXVA2Manager();
HRESULT Init();
HRESULT Init(nsACString& aFailureReason);
IUnknown* GetDXVADeviceManager() override;
@ -288,28 +307,46 @@ D3D11DXVA2Manager::GetDXVADeviceManager()
}
HRESULT
D3D11DXVA2Manager::Init()
D3D11DXVA2Manager::Init(nsACString& aFailureReason)
{
HRESULT hr;
mDevice = gfxWindowsPlatform::GetPlatform()->CreateD3D11DecoderDevice();
NS_ENSURE_TRUE(mDevice, E_FAIL);
if (!mDevice) {
aFailureReason.AssignLiteral("Failed to create D3D11 device for decoder");
return E_FAIL;
}
mDevice->GetImmediateContext(byRef(mContext));
NS_ENSURE_TRUE(mContext, E_FAIL);
if (!mContext) {
aFailureReason.AssignLiteral("Failed to get immediate context for d3d11 device");
return E_FAIL;
}
hr = wmf::MFCreateDXGIDeviceManager(&mDeviceManagerToken, byRef(mDXGIDeviceManager));
NS_ENSURE_TRUE(SUCCEEDED(hr),hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("MFCreateDXGIDeviceManager failed with code %X", hr);
return hr;
}
hr = mDXGIDeviceManager->ResetDevice(mDevice, mDeviceManagerToken);
NS_ENSURE_TRUE(SUCCEEDED(hr),hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("IMFDXGIDeviceManager::ResetDevice failed with code %X", hr);
return hr;
}
mTransform = new MFTDecoder();
hr = mTransform->Create(CLSID_VideoProcessorMFT);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("MFTDecoder::Create(CLSID_VideoProcessorMFT) failed with code %X", hr);
return hr;
}
hr = mTransform->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, ULONG_PTR(mDXGIDeviceManager.get()));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (!SUCCEEDED(hr)) {
aFailureReason = nsPrintfCString("MFTDecoder::SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER) failed with code %X", hr);
return hr;
}
return S_OK;
}
@ -465,18 +502,19 @@ D3D11DXVA2Manager::ConfigureForSize(uint32_t aWidth, uint32_t aHeight)
/* static */
DXVA2Manager*
DXVA2Manager::CreateD3D11DXVA()
DXVA2Manager::CreateD3D11DXVA(nsACString& aFailureReason)
{
// DXVA processing takes up a lot of GPU resources, so limit the number of
// videos we use DXVA with at any one time.
const uint32_t dxvaLimit =
Preferences::GetInt("media.windows-media-foundation.max-dxva-videos", 8);
if (sDXVAVideosCount == dxvaLimit) {
aFailureReason.AssignLiteral("Too many DXVA videos playing");
return nullptr;
}
nsAutoPtr<D3D11DXVA2Manager> manager(new D3D11DXVA2Manager());
HRESULT hr = manager->Init();
HRESULT hr = manager->Init(aFailureReason);
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
return manager.forget();

View File

@ -23,8 +23,8 @@ public:
// Creates and initializes a DXVA2Manager. We can use DXVA2 via either
// D3D9Ex or D3D11.
static DXVA2Manager* CreateD3D9DXVA();
static DXVA2Manager* CreateD3D11DXVA();
static DXVA2Manager* CreateD3D9DXVA(nsACString& aFailureReason);
static DXVA2Manager* CreateD3D11DXVA(nsACString& aFailureReason);
// Returns a pointer to the D3D device manager responsible for managing the
// device we're using for hardware accelerated video decoding. If we're using

View File

@ -234,10 +234,10 @@ WMFMediaDataDecoder::Drain()
}
bool
WMFMediaDataDecoder::IsHardwareAccelerated() const {
WMFMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const {
MOZ_ASSERT(!mIsShutDown);
return mMFTManager && mMFTManager->IsHardwareAccelerated();
return mMFTManager && mMFTManager->IsHardwareAccelerated(aFailureReason);
}
} // namespace mozilla

View File

@ -43,7 +43,7 @@ public:
// Destroys all resources.
virtual void Shutdown() = 0;
virtual bool IsHardwareAccelerated() const { return false; }
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { return false; }
virtual TrackInfo::TrackType GetType() = 0;
@ -72,7 +72,7 @@ public:
virtual nsresult Shutdown() override;
virtual bool IsHardwareAccelerated() const override;
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
private:

View File

@ -21,6 +21,7 @@
#include "IMFYCbCrImage.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/Preferences.h"
#include "nsPrintfCString.h"
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
@ -128,8 +129,9 @@ WMFVideoMFTManager::GetMediaSubtypeGUID()
class CreateDXVAManagerEvent : public nsRunnable {
public:
CreateDXVAManagerEvent(LayersBackend aBackend)
CreateDXVAManagerEvent(LayersBackend aBackend, nsCString& aFailureReason)
: mBackend(aBackend)
, mFailureReason(aFailureReason)
{}
NS_IMETHOD Run() {
@ -137,14 +139,15 @@ public:
if (mBackend == LayersBackend::LAYERS_D3D11 &&
Preferences::GetBool("media.windows-media-foundation.allow-d3d11-dxva", false) &&
IsWin8OrLater()) {
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA();
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(mFailureReason);
} else {
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA();
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(mFailureReason);
}
return NS_OK;
}
nsAutoPtr<DXVA2Manager> mDXVA2Manager;
LayersBackend mBackend;
nsACString& mFailureReason;
};
bool
@ -155,15 +158,19 @@ WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9)
// If we use DXVA but aren't running with a D3D layer manager then the
// readback of decoded video frames from GPU to CPU memory grinds painting
// to a halt, and makes playback performance *worse*.
if (!mDXVAEnabled ||
(mLayersBackend != LayersBackend::LAYERS_D3D9 &&
mLayersBackend != LayersBackend::LAYERS_D3D11)) {
if (!mDXVAEnabled) {
mDXVAFailureReason.AssignLiteral("Hardware video decoding disabled or blacklisted");
return false;
}
if (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
mLayersBackend != LayersBackend::LAYERS_D3D11) {
mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
return false;
}
// The DXVA manager must be created on the main thread.
nsRefPtr<CreateDXVAManagerEvent> event =
new CreateDXVAManagerEvent(aForceD3D9 ? LayersBackend::LAYERS_D3D9 : mLayersBackend);
new CreateDXVAManagerEvent(aForceD3D9 ? LayersBackend::LAYERS_D3D9 : mLayersBackend, mDXVAFailureReason);
if (NS_IsMainThread()) {
event->Run();
@ -184,7 +191,10 @@ WMFVideoMFTManager::Init()
// to d3d9.
if (!decoder && mDXVA2Manager && mDXVA2Manager->IsD3D11()) {
mDXVA2Manager = nullptr;
nsCString d3d11Failure = mDXVAFailureReason;
decoder = InitInternal(true);
mDXVAFailureReason.Append(NS_LITERAL_CSTRING("; "));
mDXVAFailureReason.Append(d3d11Failure);
}
return decoder.forget();
@ -225,7 +235,11 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9)
hr = decoder->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager);
if (SUCCEEDED(hr)) {
mUseHwAccel = true;
} else {
mDXVAFailureReason = nsPrintfCString("MFT_MESSAGE_SET_D3D_MANAGER failed with code %X", hr);
}
} else {
mDXVAFailureReason.AssignLiteral("Decoder returned false for MF_SA_D3D_AWARE");
}
}
@ -555,8 +569,9 @@ WMFVideoMFTManager::Shutdown()
}
bool
WMFVideoMFTManager::IsHardwareAccelerated() const
WMFVideoMFTManager::IsHardwareAccelerated(nsACString& aFailureReason) const
{
aFailureReason = mDXVAFailureReason;
return mDecoder && mUseHwAccel;
}

View File

@ -34,7 +34,7 @@ public:
virtual void Shutdown() override;
virtual bool IsHardwareAccelerated() const override;
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
virtual TrackInfo::TrackType GetType() override {
return TrackInfo::kVideoTrack;
@ -71,6 +71,8 @@ private:
const layers::LayersBackend mLayersBackend;
bool mUseHwAccel;
nsCString mDXVAFailureReason;
enum StreamType {
Unknown,
H264,

View File

@ -121,12 +121,12 @@ H264Converter::Shutdown()
}
bool
H264Converter::IsHardwareAccelerated() const
H264Converter::IsHardwareAccelerated(nsACString& aFailureReason) const
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated();
return mDecoder->IsHardwareAccelerated(aFailureReason);
}
return MediaDataDecoder::IsHardwareAccelerated();
return MediaDataDecoder::IsHardwareAccelerated(aFailureReason);
}
nsresult

View File

@ -34,7 +34,7 @@ public:
virtual nsresult Flush() override;
virtual nsresult Drain() override;
virtual nsresult Shutdown() override;
virtual bool IsHardwareAccelerated() const override;
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
// Return true if mimetype is H.264.
static bool IsH264(const TrackInfo& aConfig);

View File

@ -219,7 +219,7 @@ const SNAPSHOT_SCHEMA = {
type: "boolean",
},
supportsHardwareH264: {
type: "boolean",
type: "string",
},
numAcceleratedWindowsMessage: {
type: "array",