mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1885671 - run the method of getting codec supported on the background thread in order not to block the main thread. r=jrmuizel
There are modifications needed for PDMfactory and the decoder modules in order to run their methods on non-mainthread and keep them threadsafe. Differential Revision: https://phabricator.services.mozilla.com/D206420
This commit is contained in:
parent
bc6dca1d7f
commit
6a0a4e413c
@ -27,6 +27,7 @@
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
#include "mozilla/RemoteDecoderModule.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPrefs_media.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
@ -786,9 +787,11 @@ void PDMFactory::SetCDMProxy(CDMProxy* aProxy) {
|
||||
mEMEPDM = MakeRefPtr<EMEDecoderModule>(aProxy, m);
|
||||
}
|
||||
|
||||
StaticMutex sSupportedMutex;
|
||||
|
||||
/* static */
|
||||
media::MediaCodecsSupported PDMFactory::Supported(bool aForceRefresh) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
StaticMutexAutoLock lock(sSupportedMutex);
|
||||
|
||||
static auto calculate = []() {
|
||||
auto pdm = MakeRefPtr<PDMFactory>();
|
||||
|
@ -64,21 +64,28 @@ AndroidDecoderModule::AndroidDecoderModule(CDMProxy* aProxy) {
|
||||
mProxy = static_cast<MediaDrmCDMProxy*>(aProxy);
|
||||
}
|
||||
|
||||
StaticAutoPtr<nsTArray<nsCString>> AndroidDecoderModule::sSupportedSwMimeTypes;
|
||||
StaticAutoPtr<nsTArray<nsCString>> AndroidDecoderModule::sSupportedHwMimeTypes;
|
||||
StaticAutoPtr<MediaCodecsSupported> AndroidDecoderModule::sSupportedCodecs;
|
||||
/* static */ bool AndroidDecoderModule::AreSupportedMimeTypesReady() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sSupportedSwMimeTypes && sSupportedHwMimeTypes;
|
||||
}
|
||||
|
||||
/* static */ bool AndroidDecoderModule::IsSupportedCodecsReady() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sSupportedCodecs;
|
||||
}
|
||||
|
||||
/* static */
|
||||
media::MediaCodecsSupported AndroidDecoderModule::GetSupportedCodecs() {
|
||||
if (!sSupportedSwMimeTypes || !sSupportedHwMimeTypes || !sSupportedCodecs) {
|
||||
if (!AreSupportedMimeTypesReady() || !IsSupportedCodecsReady()) {
|
||||
SetSupportedMimeTypes();
|
||||
}
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return *sSupportedCodecs;
|
||||
}
|
||||
|
||||
DecodeSupportSet AndroidDecoderModule::SupportsMimeType(
|
||||
const nsACString& aMimeType) {
|
||||
if (!sSupportedSwMimeTypes) {
|
||||
if (!AreSupportedMimeTypesReady()) {
|
||||
SetSupportedMimeTypes();
|
||||
}
|
||||
|
||||
@ -135,13 +142,16 @@ DecodeSupportSet AndroidDecoderModule::SupportsMimeType(
|
||||
|
||||
// If a codec has no special handling or can't be determined from the
|
||||
// MIME type string, check if the MIME type string itself is supported.
|
||||
if (sSupportedHwMimeTypes &&
|
||||
sSupportedHwMimeTypes->Contains(TranslateMimeType(aMimeType))) {
|
||||
return DecodeSupport::HardwareDecode;
|
||||
}
|
||||
if (sSupportedSwMimeTypes &&
|
||||
sSupportedSwMimeTypes->Contains(TranslateMimeType(aMimeType))) {
|
||||
return DecodeSupport::SoftwareDecode;
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (sSupportedHwMimeTypes &&
|
||||
sSupportedHwMimeTypes->Contains(TranslateMimeType(aMimeType))) {
|
||||
return DecodeSupport::HardwareDecode;
|
||||
}
|
||||
if (sSupportedSwMimeTypes &&
|
||||
sSupportedSwMimeTypes->Contains(TranslateMimeType(aMimeType))) {
|
||||
return DecodeSupport::SoftwareDecode;
|
||||
}
|
||||
}
|
||||
return media::DecodeSupportSet{};
|
||||
}
|
||||
@ -179,21 +189,43 @@ void AndroidDecoderModule::SetSupportedMimeTypes() {
|
||||
// Inbound MIME types prefixed with SW/HW need to be processed
|
||||
void AndroidDecoderModule::SetSupportedMimeTypes(
|
||||
nsTArray<nsCString>&& aSupportedTypes) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
// Return if support is already cached
|
||||
if (sSupportedSwMimeTypes && sSupportedHwMimeTypes && sSupportedCodecs) {
|
||||
return;
|
||||
}
|
||||
if (!sSupportedSwMimeTypes) {
|
||||
sSupportedSwMimeTypes = new nsTArray<nsCString>;
|
||||
ClearOnShutdown(&sSupportedSwMimeTypes);
|
||||
if (NS_IsMainThread()) {
|
||||
ClearOnShutdown(&sSupportedSwMimeTypes);
|
||||
} else {
|
||||
Unused << NS_DispatchToMainThread(NS_NewRunnableFunction(__func__, []() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
ClearOnShutdown(&sSupportedSwMimeTypes);
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (!sSupportedHwMimeTypes) {
|
||||
sSupportedHwMimeTypes = new nsTArray<nsCString>;
|
||||
ClearOnShutdown(&sSupportedHwMimeTypes);
|
||||
if (NS_IsMainThread()) {
|
||||
ClearOnShutdown(&sSupportedHwMimeTypes);
|
||||
} else {
|
||||
Unused << NS_DispatchToMainThread(NS_NewRunnableFunction(__func__, []() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
ClearOnShutdown(&sSupportedHwMimeTypes);
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (!sSupportedCodecs) {
|
||||
sSupportedCodecs = new MediaCodecsSupported();
|
||||
ClearOnShutdown(&sSupportedCodecs);
|
||||
if (NS_IsMainThread()) {
|
||||
ClearOnShutdown(&sSupportedCodecs);
|
||||
} else {
|
||||
Unused << NS_DispatchToMainThread(NS_NewRunnableFunction(__func__, []() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
ClearOnShutdown(&sSupportedCodecs);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
DecodeSupportSet support;
|
||||
|
@ -54,16 +54,25 @@ class AndroidDecoderModule : public PlatformDecoderModule {
|
||||
private:
|
||||
explicit AndroidDecoderModule(CDMProxy* aProxy = nullptr);
|
||||
virtual ~AndroidDecoderModule() = default;
|
||||
|
||||
static bool AreSupportedMimeTypesReady();
|
||||
static bool IsSupportedCodecsReady();
|
||||
|
||||
RefPtr<MediaDrmCDMProxy> mProxy;
|
||||
// SW compatible MIME type strings
|
||||
static StaticAutoPtr<nsTArray<nsCString>> sSupportedSwMimeTypes;
|
||||
static inline StaticAutoPtr<nsTArray<nsCString>> sSupportedSwMimeTypes
|
||||
MOZ_GUARDED_BY(sMutex);
|
||||
// HW compatible MIME type strings
|
||||
static StaticAutoPtr<nsTArray<nsCString>> sSupportedHwMimeTypes;
|
||||
static inline StaticAutoPtr<nsTArray<nsCString>> sSupportedHwMimeTypes
|
||||
MOZ_GUARDED_BY(sMutex);
|
||||
// EnumSet containing SW/HW codec support information parsed from
|
||||
// MIME type strings. If a specific codec could not be determined
|
||||
// it will not be included in this EnumSet. All supported MIME type strings
|
||||
// are still stored in sSupportedSwMimeTypes and sSupportedHwMimeTypes.
|
||||
static StaticAutoPtr<media::MediaCodecsSupported> sSupportedCodecs;
|
||||
static inline StaticAutoPtr<media::MediaCodecsSupported> sSupportedCodecs
|
||||
MOZ_GUARDED_BY(sMutex);
|
||||
|
||||
static inline StaticMutex sMutex;
|
||||
};
|
||||
|
||||
extern LazyLogModule sAndroidDecoderModuleLog;
|
||||
|
@ -85,13 +85,8 @@ static bool IsRemoteAcceleratedCompositor(
|
||||
ident.mParentProcessType == GeckoProcessType_GPU;
|
||||
}
|
||||
|
||||
static Atomic<bool> sSupportedTypesInitialized(false);
|
||||
static EnumSet<WMFStreamType> sSupportedTypes;
|
||||
static EnumSet<WMFStreamType> sLackOfExtensionTypes;
|
||||
|
||||
/* static */
|
||||
void WMFDecoderModule::Init(Config aConfig) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
|
||||
if (XRE_IsContentProcess()) {
|
||||
// If we're in the content process and the UseGPUDecoder pref is set, it
|
||||
// means that we've given up on the GPU process (it's been crashing) so we
|
||||
@ -134,6 +129,7 @@ void WMFDecoderModule::Init(Config aConfig) {
|
||||
sDXVAEnabled = sDXVAEnabled && hwVideo;
|
||||
|
||||
mozilla::mscom::EnsureMTA([&]() {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
// Store the supported MFT decoders.
|
||||
sSupportedTypes.clear();
|
||||
sLackOfExtensionTypes.clear();
|
||||
@ -163,7 +159,10 @@ void WMFDecoderModule::Init(Config aConfig) {
|
||||
}
|
||||
});
|
||||
|
||||
sSupportedTypesInitialized = true;
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
sSupportedTypesInitialized = true;
|
||||
}
|
||||
|
||||
WmfDecoderModuleMarkerAndLog("WMFInit Result",
|
||||
"WMFDecoderModule::Init finishing");
|
||||
@ -270,15 +269,13 @@ HRESULT WMFDecoderModule::CreateMFTDecoder(const WMFStreamType& aType,
|
||||
/* static */
|
||||
bool WMFDecoderModule::CanCreateMFTDecoder(const WMFStreamType& aType) {
|
||||
MOZ_ASSERT(WMFStreamType::Unknown < aType && aType < WMFStreamType::SENTINEL);
|
||||
if (!sSupportedTypesInitialized) {
|
||||
if (NS_IsMainThread()) {
|
||||
Init();
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableFunction("WMFDecoderModule::Init", [&]() { Init(); });
|
||||
SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(),
|
||||
runnable);
|
||||
}
|
||||
bool hasInitialized = false;
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
hasInitialized = sSupportedTypesInitialized;
|
||||
}
|
||||
if (!hasInitialized) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Check prefs here rather than CreateMFTDecoder so that prefs aren't baked
|
||||
@ -324,7 +321,7 @@ bool WMFDecoderModule::CanCreateMFTDecoder(const WMFStreamType& aType) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sSupportedTypes.contains(aType);
|
||||
}
|
||||
|
||||
@ -380,6 +377,7 @@ media::DecodeSupportSet WMFDecoderModule::Supports(
|
||||
return media::DecodeSupport::SoftwareDecode;
|
||||
}
|
||||
}
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
return sLackOfExtensionTypes.contains(type)
|
||||
? media::DecodeSupport::UnsureDueToLackOfExtension
|
||||
: media::DecodeSupportSet{};
|
||||
|
@ -63,6 +63,12 @@ class WMFDecoderModule : public PlatformDecoderModule {
|
||||
|
||||
WMFDecoderModule() = default;
|
||||
virtual ~WMFDecoderModule() = default;
|
||||
|
||||
static inline StaticMutex sMutex;
|
||||
static inline bool sSupportedTypesInitialized MOZ_GUARDED_BY(sMutex) = false;
|
||||
static inline EnumSet<WMFStreamType> sSupportedTypes MOZ_GUARDED_BY(sMutex);
|
||||
static inline EnumSet<WMFStreamType> sLackOfExtensionTypes
|
||||
MOZ_GUARDED_BY(sMutex);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -107,62 +107,58 @@ using namespace layers;
|
||||
static GPUParent* sGPUParent;
|
||||
|
||||
static void ReportHardwareMediaCodecSupportIfNeeded() {
|
||||
MOZ_ASSERT(!NS_IsMainThread(), "Should not block main thread");
|
||||
// We only need to report the result once.
|
||||
static bool sReported = false;
|
||||
if (sReported) {
|
||||
return;
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
NS_GetCurrentThread()->Dispatch(NS_NewRunnableFunction(
|
||||
"GPUParent:ReportHardwareMediaCodecSupportIfNeeded", []() {
|
||||
// Only report telemetry when hardware decoding is available.
|
||||
if (!gfx::gfxVars::IsInitialized() ||
|
||||
!gfx::gfxVars::CanUseHardwareVideoDecoding()) {
|
||||
return;
|
||||
}
|
||||
sReported = true;
|
||||
// Only report telemetry when hardware decoding is available.
|
||||
if (!gfx::gfxVars::IsInitialized() ||
|
||||
!gfx::gfxVars::CanUseHardwareVideoDecoding()) {
|
||||
return;
|
||||
}
|
||||
sReported = true;
|
||||
|
||||
// TODO : we can remove this after HEVC is enabled by default.
|
||||
// HEVC is not enabled. We need to force to enable it in order to know
|
||||
// its support as well, and it would be turn off later.
|
||||
if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
|
||||
WMFDecoderModule::Init(WMFDecoderModule::Config::ForceEnableHEVC);
|
||||
}
|
||||
const auto support = PDMFactory::Supported(true /* force refresh */);
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::H264HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT, u"h264"_ns,
|
||||
true);
|
||||
}
|
||||
if (support.contains(mozilla::media::MediaCodecsSupport::VP8HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT, u"vp8"_ns,
|
||||
true);
|
||||
}
|
||||
if (support.contains(mozilla::media::MediaCodecsSupport::VP9HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT, u"vp9"_ns,
|
||||
true);
|
||||
}
|
||||
if (support.contains(mozilla::media::MediaCodecsSupport::AV1HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT, u"av1"_ns,
|
||||
true);
|
||||
}
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::HEVCHardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT, u"hevc"_ns,
|
||||
true);
|
||||
}
|
||||
if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
|
||||
WMFDecoderModule::Init();
|
||||
}
|
||||
|
||||
// TODO : we can remove this after HEVC is enabled by default.
|
||||
// HEVC is not enabled. We need to force to enable it in order to know
|
||||
// its support as well, and it would be turn off later.
|
||||
if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
|
||||
WMFDecoderModule::Init(WMFDecoderModule::Config::ForceEnableHEVC);
|
||||
}
|
||||
const auto support = PDMFactory::Supported(true /* force refresh */);
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::H264HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
|
||||
u"h264"_ns, true);
|
||||
}
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::VP8HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
|
||||
u"vp8"_ns, true);
|
||||
}
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::VP9HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
|
||||
u"vp9"_ns, true);
|
||||
}
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::AV1HardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
|
||||
u"av1"_ns, true);
|
||||
}
|
||||
if (support.contains(
|
||||
mozilla::media::MediaCodecsSupport::HEVCHardwareDecode)) {
|
||||
Telemetry::ScalarSet(
|
||||
Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
|
||||
u"hevc"_ns, true);
|
||||
}
|
||||
if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
|
||||
WMFDecoderModule::Init();
|
||||
}
|
||||
}));
|
||||
#endif
|
||||
// TODO : in the future, when we have GPU procss on MacOS, then we can report
|
||||
// HEVC usage as well.
|
||||
@ -459,16 +455,19 @@ mozilla::ipc::IPCResult GPUParent::RecvInit(
|
||||
// Dispatch a task to run when idle that will determine which codecs are
|
||||
// usable. The primary goal is to determine if the media feature pack is
|
||||
// installed.
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThreadQueue(
|
||||
NS_NewRunnableFunction(
|
||||
"GPUParent::Supported",
|
||||
[]() {
|
||||
auto supported = PDMFactory::Supported();
|
||||
Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
|
||||
supported);
|
||||
ReportHardwareMediaCodecSupportIfNeeded();
|
||||
}),
|
||||
2000 /* 2 seconds timeout */, EventQueuePriority::Idle));
|
||||
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
NS_NewRunnableFunction("GPUParent::Supported", []() {
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"GPUParent::UpdateMediaCodecsSupported",
|
||||
[supported = PDMFactory::Supported()]() {
|
||||
Unused << GPUParent::GetSingleton()
|
||||
->SendUpdateMediaCodecsSupported(supported);
|
||||
}));
|
||||
ReportHardwareMediaCodecSupportIfNeeded();
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
NS_DispatchBackgroundTask(task, nsIEventTarget::DISPATCH_NORMAL));
|
||||
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS,
|
||||
mLaunchTime);
|
||||
@ -555,10 +554,20 @@ mozilla::ipc::IPCResult GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
|
||||
if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) {
|
||||
// The capabilities of the system may have changed, force a refresh by
|
||||
// re-initializing the WMF PDM.
|
||||
WMFDecoderModule::Init();
|
||||
Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
|
||||
PDMFactory::Supported(true /* force refresh */));
|
||||
ReportHardwareMediaCodecSupportIfNeeded();
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
NS_NewRunnableFunction("GPUParent::RecvUpdateVar", []() {
|
||||
WMFDecoderModule::Init();
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"GPUParent::UpdateMediaCodecsSupported",
|
||||
[supported =
|
||||
PDMFactory::Supported(true /* force refresh */)]() {
|
||||
Unused << GPUParent::GetSingleton()
|
||||
->SendUpdateMediaCodecsSupported(supported);
|
||||
}));
|
||||
ReportHardwareMediaCodecSupportIfNeeded();
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
NS_DispatchBackgroundTask(task, nsIEventTarget::DISPATCH_NORMAL));
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user