Files
palemoon27/dom/media/platforms/wmf/WMFDecoderModule.cpp
T
roytam1 0b4ed75d7e import changes from `dev' branch of rmottola/Arctic-Fox:
- formatting (49c876691)
- adapted  Bug 1163227: Part5: Increase verbosity content for debugging purposes. r=cpearce (cfca0b7bf)
- Bug 1184634 - Rename MediaPromise to MozPromise. r=gerald (e9617bf70)
- space (c5bafde74)
- Bug 1158293 - Fix ResumeStateMachine()'s seek handling r=cpearce (67dbe7dfc)
- reapply part of Bug 1158448 Part 2 (a953e6c6b)
- Bug 1184634 - Rename "TaskQueue()" accessor to "OwnerThread()". r=gerald (118965bae)
- Bug 1145411: Reduce Apple audio decoder verbosity. r=mattwoodrow (a9f2c4092)
- Bug 1174055 - Remove some now uncalled WMF functions. r=jya (8cddc9d0e)
- Bug 1179094: Use TimeUnit in PlatformDecoderModule. r=cpearce (3d8fd9cd7)
- align warnings to Bug 1154133 - Remove sync dispatches in EMEDecryptor, and mark MediaTaskQueue::SyncDispatch as deprecated. (d93e2f431)
- align some permissions and comments (54eb9e910)
- Bug 1155268 - Add checked methods to convert from an AbstractThread to a concrete type. r=cpearce (5deff5f04)
- align comment (c508b1aaf)
- Bug 857895 - Only enforce tail dispatch if both source and dest support it. r=bholley (2e6d03096)
- Bug 1184634 - Rename MediaTaskQueue to TaskQueue. r=gerald (5f18c2616)
- Bug 1127656 - Remove class inheritance hierarchy from gonk PlatformDeocdeModule. r=ajones (eebf0eb20)
- Bug 1184634 - Move various includes into the mozilla namespace. r=gerald (a9b516578)
- Bug 1190636 - Replace AutoStringVector with Rooted usage; r=njn (5d287ee81)
- Bug 1190911 - Replace AutoIdValueVector with normal Rooted usage; r=jonco (b6c8ce668)
- Bug 1149343 - Followup to fix bustage on a CLOSED TREE (f20f9f1a2)
- Bug 1172841. Set number of WMF decoder threads based on CPU count. r=cpearce (af74b7654)
- Bug 1166760 - Query audio sampling rate & channel number from codec. r=sotaro (ee5fb569a)
-  Bug 1175071 - Remove those codes which handles ADTS. r=jya. (00b1d3dad)
- Bug 1178682 - Reject the decoded sample if timestamp is revert. r=sotaro (4cd029e8c)
2021-07-27 16:39:15 +08:00

215 lines
6.3 KiB
C++

/* -*- 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 "WMF.h"
#include "WMFDecoderModule.h"
#include "WMFVideoMFTManager.h"
#include "WMFAudioMFTManager.h"
#include "mozilla/Preferences.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Services.h"
#include "WMFMediaDataDecoder.h"
#include "nsIWindowsRegKey.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIGfxInfo.h"
#include "GfxDriverInfo.h"
#include "gfxWindowsPlatform.h"
#include "nsServiceManagerUtils.h" // for do_GetService
#include "MediaInfo.h"
#include "prsystem.h"
namespace mozilla {
static bool sIsWMFEnabled = false;
static bool sDXVAEnabled = false;
static int sNumDecoderThreads = -1;
WMFDecoderModule::WMFDecoderModule()
: mWMFInitialized(false)
{
}
WMFDecoderModule::~WMFDecoderModule()
{
if (mWMFInitialized) {
DebugOnly<HRESULT> hr = wmf::MFShutdown();
NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
}
}
void
WMFDecoderModule::DisableHardwareAcceleration()
{
sDXVAEnabled = false;
}
static void
SetNumOfDecoderThreads()
{
MOZ_ASSERT(NS_IsMainThread(), "Preferences can only be read on main thread");
int32_t numCores = PR_GetNumberOfProcessors();
// If we have more than 4 cores, let the decoder decide how many threads.
// On an 8 core machine, WMF chooses 4 decoder threads
const int WMF_DECODER_DEFAULT = -1;
int32_t prefThreadCount = Preferences::GetInt("media.wmf.decoder.thread-count", -1);
if (prefThreadCount != WMF_DECODER_DEFAULT) {
sNumDecoderThreads = std::max(prefThreadCount, 1);
} else if (numCores > 4) {
sNumDecoderThreads = WMF_DECODER_DEFAULT;
} else {
sNumDecoderThreads = std::max(numCores - 1, 1);
}
}
/* static */
void
WMFDecoderModule::Init()
{
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
sIsWMFEnabled = Preferences::GetBool("media.windows-media-foundation.enabled", false);
sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
SetNumOfDecoderThreads();
}
/* static */
int
WMFDecoderModule::GetNumDecoderThreads()
{
return sNumDecoderThreads;
}
nsresult
WMFDecoderModule::Startup()
{
if (sIsWMFEnabled) {
mWMFInitialized = SUCCEEDED(wmf::MFStartup());
}
return mWMFInitialized ? NS_OK : NS_ERROR_FAILURE;
}
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new WMFMediaDataDecoder(new WMFVideoMFTManager(aConfig,
aLayersBackend,
aImageContainer,
sDXVAEnabled && ShouldUseDXVA(aConfig)),
aVideoTaskQueue,
aCallback);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
MediaDataDecoderCallback* aCallback)
{
nsRefPtr<MediaDataDecoder> decoder =
new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig),
aAudioTaskQueue,
aCallback);
return decoder.forget();
}
bool
WMFDecoderModule::ShouldUseDXVA(const VideoInfo& aConfig) const
{
static bool isAMD = false;
static bool initialized = false;
if (!initialized) {
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
nsAutoString vendor;
gfxInfo->GetAdapterVendorID(vendor);
isAMD = vendor.Equals(widget::GfxDriverInfo::GetDeviceVendor(widget::VendorAMD), nsCaseInsensitiveStringComparator()) ||
vendor.Equals(widget::GfxDriverInfo::GetDeviceVendor(widget::VendorATI), nsCaseInsensitiveStringComparator());
initialized = true;
}
if (!isAMD) {
return true;
}
// Don't use DXVA for 4k videos or above, since it seems to perform poorly.
return aConfig.mDisplay.width <= 1920 && aConfig.mDisplay.height <= 1200;
}
bool
WMFDecoderModule::SupportsSharedDecoders(const VideoInfo& aConfig) const
{
// If DXVA is enabled, but we're not going to use it for this specific config, then
// we can't use the shared decoder.
return !sDXVAEnabled || ShouldUseDXVA(aConfig);
}
bool
WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType)
{
return aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp8") ||
aMimeType.EqualsLiteral("video/webm; codecs=vp9") ||
aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mpeg");
}
PlatformDecoderModule::ConversionRequired
WMFDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
{
if (aConfig.IsVideo() &&
(aConfig.mMimeType.EqualsLiteral("video/avc") ||
aConfig.mMimeType.EqualsLiteral("video/mp4"))) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
static bool
ClassesRootRegKeyExists(const nsAString& aRegKeyPath)
{
nsresult rv;
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
aRegKeyPath,
nsIWindowsRegKey::ACCESS_READ);
if (NS_FAILED(rv)) {
return false;
}
regKey->Close();
return true;
}
/* static */ bool
WMFDecoderModule::HasH264()
{
// CLSID_CMSH264DecoderMFT
return ClassesRootRegKeyExists(
NS_LITERAL_STRING("CLSID\\{32D186A7-218F-4C75-8876-DD77273A8999}"));
}
/* static */ bool
WMFDecoderModule::HasAAC()
{
// CLSID_CMSAACDecMFT
return ClassesRootRegKeyExists(
NS_LITERAL_STRING("CLSID\\{62CE7E72-4C71-4D20-B15D-452831A87D9D}"));
}
} // namespace mozilla