Bug 1674043 - P6. Remove sync PDecoderMananger::Supports API. r=mattwoodrow,bryce,mjf,ipc-reviewers,nika

In bug 1595994 we attempted to streamline the ability to determine which decoder was available regardless of the process they would be running in. This was subsequently done via the PDMFactory.

As there are several JS API that can query which codec are supported, it requires a synchronous mechanism.
This allowed to make a determination during the PlatformDecoderModule::Supports call, depending on which process it was going to be called frome.

Having a synchronous IPC call to the RemoteDecoderManagerParent has too many caveats to be workable.
So what we do instead is first determine at launch if the required external framework are available and pass this information to each content process.

When checking if a decoder is available, we make a best guess at determining if the PDM would support such codec, without actually loading such framework when running in the content process.

Supports can no longer make a decision based on the process currently running and as such PDM::CreateAudio/VideoDecoder using an optional system framework now need to further check the validity of the CreateDecoderParam argument.

Differential Revision: https://phabricator.services.mozilla.com/D95245
This commit is contained in:
Jean-Yves Avenard 2020-11-04 02:22:33 +00:00
Родитель bedf73be6e
Коммит c938c7416c
16 изменённых файлов: 302 добавлений и 117 удалений

Просмотреть файл

@ -1306,6 +1306,7 @@ void ContentChild::InitXPCOM(
DataStorage::SetCachedStorageEntries(aXPCOMInit.dataStorage());
PDMFactory::SetSupported(aXPCOMInit.codecsSupported());
// Initialize the RemoteDecoderManager thread and its associated PBackground
// channel.
RemoteDecoderManagerChild::Init();

Просмотреть файл

@ -38,6 +38,7 @@
#include "Geolocation.h"
#include "GfxInfoBase.h"
#include "MMPrinter.h"
#include "PDMFactory.h"
#include "PreallocatedProcessManager.h"
#include "ProcessPriorityManager.h"
#include "SandboxHal.h"
@ -2761,6 +2762,10 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
// Send the dynamic scalar definitions to the new process.
TelemetryIPC::GetDynamicScalarDefinitions(xpcomInit.dynamicScalarDefs());
// Pre-calculate the various PlatformDecoderModule (PDM) supported on this
// machine.
xpcomInit.codecsSupported() = PDMFactory::Supported();
// Must send screen info before send initialData
ScreenManager& screenManager = ScreenManager::GetSingleton();
screenManager.CopyScreensToRemote(this);

Просмотреть файл

@ -132,6 +132,7 @@ using refcounted class nsILayoutHistoryState from "nsILayoutHistoryState.h";
using class mozilla::dom::SessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
using nsPoint from "mozilla/GfxMessageUtils.h";
using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
union ChromeRegistryItem
{
@ -312,6 +313,7 @@ struct XPCOMInitData
nsCString[] requestedLocales;
DynamicScalarDefinition[] dynamicScalarDefs;
SystemParameterKVPair[] systemParameters;
MediaCodecsSupported codecsSupported;
};
struct VisitedQueryResult

Просмотреть файл

@ -33,11 +33,6 @@ sync protocol PRemoteDecoderManager
manages PRemoteDecoder;
parent:
sync Supports(RemoteDecoderInfoIPDL info,
TextureFactoryIdentifier? identifier)
returns (bool success,
DecoderDoctorDiagnostics diagnostics);
sync PRemoteDecoder(RemoteDecoderInfoIPDL info,
OptionSet options,
TextureFactoryIdentifier? identifier)

Просмотреть файл

@ -64,13 +64,6 @@ ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
StaticRefPtr<ShutdownObserver> sObserver;
static Maybe<layers::TextureFactoryIdentifier> MaybeTextureFactoryIdentifier(
const SupportDecoderParams& aParams) {
return aParams.mKnowsCompositor
? Some(aParams.mKnowsCompositor->GetTextureFactoryIdentifier())
: Nothing();
}
/* static */
void RemoteDecoderManagerChild::Init() {
MOZ_ASSERT(NS_IsMainThread());
@ -186,41 +179,18 @@ nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() {
bool RemoteDecoderManagerChild::Supports(
RemoteDecodeIn aLocation, const SupportDecoderParams& aParams,
DecoderDoctorDiagnostics* aDiagnostics) {
bool supports = false;
DecoderDoctorDiagnostics diagnostics;
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (managerThread) {
RefPtr<Runnable> task =
NS_NewRunnableFunction("RemoteDecoderManager::Supports", [&]() {
auto* rdm = GetSingleton(aLocation);
if (!rdm) {
// The RDD process failed to launch. Fail for now.
// Creation will be attempted again later.
return;
}
const auto& trackInfo = aParams.mConfig;
if (trackInfo.GetAsVideoInfo()) {
VideoDecoderInfoIPDL info(*trackInfo.GetAsVideoInfo(),
aParams.mRate.mValue);
Unused << rdm->SendSupports(info,
MaybeTextureFactoryIdentifier(aParams),
&supports, &diagnostics);
} else if (trackInfo.GetAsAudioInfo()) {
Unused << rdm->SendSupports(*trackInfo.GetAsAudioInfo(), Nothing(),
&supports, &diagnostics);
}
});
// If we've already got shutdown, the dispatch will fail and SyncRunnable
// will immediately return.
SyncRunnable::DispatchToThread(managerThread, task);
RefPtr<PDMFactory> pdm;
switch (aLocation) {
case RemoteDecodeIn::RddProcess:
pdm = PDMFactory::PDMFactoryForRdd();
break;
case RemoteDecodeIn::GpuProcess:
pdm = PDMFactory::PDMFactoryForGpu();
break;
default:
return false;
}
if (aDiagnostics) {
*aDiagnostics = diagnostics;
}
return supports;
return pdm->Supports(aParams, aDiagnostics);
}
/* static */

Просмотреть файл

@ -227,40 +227,6 @@ void RemoteDecoderManagerParent::Open(
void RemoteDecoderManagerParent::ActorDealloc() { Release(); }
mozilla::ipc::IPCResult RemoteDecoderManagerParent::RecvSupports(
const RemoteDecoderInfoIPDL& aInfo,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier, bool* aSuccess,
DecoderDoctorDiagnostics* aDiagnostics) {
auto& factory = EnsurePDMFactory();
MediaResult error(NS_OK);
// It's important to initialize aSuccess because it is passed uninitialized
// which will cause an assert on the receiving side.
*aSuccess = false;
if (aInfo.type() == RemoteDecoderInfoIPDL::TAudioInfo) {
SupportDecoderParams params(aInfo.get_AudioInfo(), &error);
*aSuccess = factory.Supports(params, aDiagnostics);
} else if (aInfo.type() == RemoteDecoderInfoIPDL::TVideoDecoderInfoIPDL) {
RefPtr<KnowsCompositorVideo> knowsCompositor;
if (aIdentifier) {
// Check to see if we have a direct PVideoBridge connection to the
// destination process specified in aIdentifier, and create a
// KnowsCompositor representing that connection if so. If this fails, then
// we fall back to returning the decoded frames directly via Output().
knowsCompositor =
KnowsCompositorVideo::TryCreateForIdentifier(*aIdentifier);
}
const VideoDecoderInfoIPDL& info = aInfo.get_VideoDecoderInfoIPDL();
SupportDecoderParams params(info.videoInfo(), knowsCompositor,
media::VideoFrameRate(info.framerate()),
&error);
*aSuccess = factory.Supports(params, aDiagnostics);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteDecoderManagerParent::RecvReadback(
const SurfaceDescriptorGPUVideo& aSD, SurfaceDescriptor* aResult) {
const SurfaceDescriptorRemoteDecoder& sd = aSD;

Просмотреть файл

@ -22,7 +22,6 @@
#include "VorbisDecoder.h"
#include "WAVDecoder.h"
#include "gfxConfig.h"
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
namespace mozilla {

Просмотреть файл

@ -53,6 +53,10 @@
namespace mozilla {
// Set on the main thread, in content processes before any PDMFactory will ever
// be created; never modified after.
static Maybe<PDMFactory::MediaCodecsSupported> sSupported;
extern already_AddRefed<PlatformDecoderModule> CreateNullDecoderModule();
class PDMFactoryImpl final {
@ -62,7 +66,14 @@ class PDMFactoryImpl final {
InitGpuPDMs();
} else if (XRE_IsRDDProcess()) {
InitRddPDMs();
} else if (XRE_IsContentProcess()) {
MOZ_DIAGNOSTIC_ASSERT(sSupported.isSome(),
"PDMFactory accessed while not initialized");
InitContentPDMs();
} else {
MOZ_DIAGNOSTIC_ASSERT(
XRE_IsParentProcess(),
"PDMFactory is only usable in the Parent/GPU/RDD/Content process");
InitDefaultPDMs();
}
}
@ -95,6 +106,27 @@ class PDMFactoryImpl final {
#endif
}
void InitContentPDMs() {
#ifdef XP_WIN
if (!IsWin7AndPre2000Compatible()) {
WMFDecoderModule::Init();
}
#endif
#ifdef MOZ_APPLEMEDIA
AppleDecoderModule::Init();
#endif
#ifdef MOZ_OMX
OmxDecoderModule::Init();
#endif
#ifdef MOZ_FFVPX
FFVPXRuntimeLinker::Init();
#endif
#ifdef MOZ_FFMPEG
FFmpegRuntimeLinker::Init();
#endif
RemoteDecoderManagerChild::Init();
}
void InitDefaultPDMs() {
#ifdef XP_WIN
if (!IsWin7AndPre2000Compatible()) {
@ -113,9 +145,6 @@ class PDMFactoryImpl final {
#ifdef MOZ_FFMPEG
FFmpegRuntimeLinker::Init();
#endif
if (XRE_IsContentProcess()) {
RemoteDecoderManagerChild::Init();
}
}
};
@ -199,6 +228,31 @@ PDMFactory::PDMFactory() {
CreateNullPDM();
}
PDMFactory::PDMFactory(const RemoteDecodeIn& aProcess) {
switch (aProcess) {
case RemoteDecodeIn::RddProcess:
CreateRddPDMs();
break;
case RemoteDecodeIn::GpuProcess:
CreateGpuPDMs();
break;
default:
MOZ_CRASH("Not to be used for any other process");
}
}
/* static */
already_AddRefed<PDMFactory> PDMFactory::PDMFactoryForRdd() {
RefPtr<PDMFactory> pdm = new PDMFactory(RemoteDecodeIn::RddProcess);
return pdm.forget();
}
/* static */
already_AddRefed<PDMFactory> PDMFactory::PDMFactoryForGpu() {
RefPtr<PDMFactory> pdm = new PDMFactory(RemoteDecodeIn::GpuProcess);
return pdm.forget();
}
/* static */
void PDMFactory::EnsureInit() {
{
@ -383,13 +437,17 @@ void PDMFactory::CreatePDMs() {
CreateGpuPDMs();
} else if (XRE_IsRDDProcess()) {
CreateRddPDMs();
} else if (XRE_IsContentProcess()) {
CreateContentPDMs();
} else {
MOZ_DIAGNOSTIC_ASSERT(
XRE_IsParentProcess(),
"PDMFactory is only usable in the Parent/GPU/RDD/Content process");
CreateDefaultPDMs();
}
}
void PDMFactory::CreateGpuPDMs() {
MOZ_ASSERT(XRE_IsGPUProcess());
#ifdef XP_WIN
if (StaticPrefs::media_wmf_enabled() && !IsWin7AndPre2000Compatible()) {
CreateAndStartupPDM<WMFDecoderModule>();
@ -398,7 +456,6 @@ void PDMFactory::CreateGpuPDMs() {
}
void PDMFactory::CreateRddPDMs() {
MOZ_ASSERT(XRE_IsRDDProcess());
#ifdef XP_WIN
if (StaticPrefs::media_wmf_enabled() &&
StaticPrefs::media_rdd_wmf_enabled()) {
@ -428,14 +485,12 @@ void PDMFactory::CreateRddPDMs() {
CreateAndStartupPDM<AgnosticDecoderModule>();
}
void PDMFactory::CreateDefaultPDMs() {
MOZ_ASSERT(!XRE_IsGPUProcess() && !XRE_IsRDDProcess());
void PDMFactory::CreateContentPDMs() {
if (StaticPrefs::media_gpu_process_decoder()) {
CreateAndStartupPDM<RemoteDecoderModule>(RemoteDecodeIn::GpuProcess);
}
if (StaticPrefs::media_rdd_process_enabled() &&
BrowserTabsRemoteAutostart()) {
if (StaticPrefs::media_rdd_process_enabled()) {
CreateAndStartupPDM<RemoteDecoderModule>(RemoteDecodeIn::RddProcess);
}
@ -484,6 +539,52 @@ void PDMFactory::CreateDefaultPDMs() {
}
}
void PDMFactory::CreateDefaultPDMs() {
#ifdef XP_WIN
if (StaticPrefs::media_wmf_enabled() && !IsWin7AndPre2000Compatible()) {
RefPtr<WMFDecoderModule> m = MakeAndAddRef<WMFDecoderModule>();
if (!StartupPDM(m.forget())) {
mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad;
}
} else if (StaticPrefs::media_decoder_doctor_wmf_disabled_is_failure()) {
mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad;
}
#endif
#ifdef MOZ_APPLEMEDIA
CreateAndStartupPDM<AppleDecoderModule>();
#endif
#ifdef MOZ_OMX
if (StaticPrefs::media_omx_enabled()) {
CreateAndStartupPDM<OmxDecoderModule>();
}
#endif
#ifdef MOZ_FFVPX
if (StaticPrefs::media_ffvpx_enabled()) {
CreateAndStartupPDM<FFVPXRuntimeLinker>();
}
#endif
#ifdef MOZ_FFMPEG
if (StaticPrefs::media_ffmpeg_enabled() &&
!CreateAndStartupPDM<FFmpegRuntimeLinker>()) {
mFailureFlags += DecoderDoctorDiagnostics::Flags::FFmpegFailedToLoad;
}
#endif
#ifdef MOZ_WIDGET_ANDROID
if (StaticPrefs::media_android_media_codec_enabled()) {
StartupPDM(AndroidDecoderModule::Create(),
StaticPrefs::media_android_media_codec_preferred());
}
#endif
CreateAndStartupPDM<AgnosticDecoderModule>();
if (StaticPrefs::media_gmp_decoder_enabled() &&
!CreateAndStartupPDM<GMPDecoderModule>()) {
mFailureFlags += DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup;
}
}
void PDMFactory::CreateNullPDM() {
mNullPDM = CreateNullDecoderModule();
MOZ_ASSERT(mNullPDM && NS_SUCCEEDED(mNullPDM->Startup()));
@ -535,4 +636,56 @@ void PDMFactory::SetCDMProxy(CDMProxy* aProxy) {
mEMEPDM = MakeRefPtr<EMEDecoderModule>(aProxy, m);
}
/* static */
PDMFactory::MediaCodecsSupported PDMFactory::Supported() {
if (XRE_IsContentProcess()) {
return *sSupported;
}
MOZ_ASSERT(XRE_IsParentProcess());
static MediaCodecsSupported supported = []() {
auto pdm = MakeRefPtr<PDMFactory>();
MediaCodecsSupported supported;
// H264 and AAC depends on external framework that must be dynamically
// loaded.
// We currently only ship a single PDM per platform able to decode AAC or
// H264. As such we can assert that being able to create a H264 or AAC
// decoder indicates that with WMF on Windows or FFmpeg on Unixes is
// available.
// This logic will have to be revisited if a PDM supporting either codec
// will be added in addition to the WMF and FFmpeg PDM (such as OpenH264)
if (pdm->SupportsMimeType("video/avc"_ns, nullptr)) {
supported += MediaCodecs::H264;
}
if (pdm->SupportsMimeType("audio/mp4a-latm"_ns, nullptr)) {
supported += MediaCodecs::AAC;
}
// MP3 can be either decoded by ffvpx or WMF/FFmpeg
if (pdm->SupportsMimeType("audio/mpeg"_ns, nullptr)) {
supported += MediaCodecs::MP3;
}
// The codecs below are potentially always supported as we ship native
// support for them. If they are disabled through pref, it will be handled
// in MediaDecoder class that could use those.
supported += MediaCodecs::VP9;
supported += MediaCodecs::VP8;
supported += MediaCodecs::AV1;
supported += MediaCodecs::Theora;
supported += MediaCodecs::Opus;
supported += MediaCodecs::Vorbis;
supported += MediaCodecs::Flac;
supported += MediaCodecs::Wave;
return supported;
}();
return supported;
}
/* static */
void PDMFactory::SetSupported(const MediaCodecsSupported& aSupported) {
MOZ_ASSERT(NS_IsMainThread());
sSupported = Some(aSupported);
}
} // namespace mozilla

Просмотреть файл

@ -18,6 +18,7 @@ namespace mozilla {
class PDMFactoryImpl;
template <class T>
class StaticAutoPtr;
enum class RemoteDecodeIn;
class PDMFactory final {
public:
@ -25,6 +26,11 @@ class PDMFactory final {
PDMFactory();
// To be called in the content process only, used to determine which PDMs are
// usable in their respective process.
static already_AddRefed<PDMFactory> PDMFactoryForRdd();
static already_AddRefed<PDMFactory> PDMFactoryForGpu();
// Factory method that creates the appropriate PlatformDecoderModule for
// the platform we're running on. Caller is responsible for deleting this
// instance. It's expected that there will be multiple
@ -50,13 +56,42 @@ class PDMFactory final {
static constexpr int kYUV422 = 2;
static constexpr int kYUV444 = 3;
/*
* All the codecs we support
*/
enum class MediaCodecs {
H264,
VP9,
VP8,
AV1,
Theora,
AAC,
MP3,
Opus,
Vorbis,
Flac,
Wave,
SENTINEL,
};
using MediaCodecsSupported = EnumSet<MediaCodecs>;
static MediaCodecsSupported Supported();
static void SetSupported(const MediaCodecsSupported& aSupported);
private:
virtual ~PDMFactory() = default;
// Will set PDM list for the required process.
// This is used to determine which PDMs are available on the given process
// from the content process.
explicit PDMFactory(const RemoteDecodeIn& aProcess);
void CreatePDMs();
void CreateNullPDM();
void CreateGpuPDMs();
void CreateRddPDMs();
void CreateContentPDMs();
void CreateDefaultPDMs();
template <typename DECODER_MODULE, typename... ARGS>
@ -89,6 +124,14 @@ class PDMFactory final {
static StaticMutex sMonitor;
};
// Used for IPDL serialization.
// The 'value' have to be the biggest enum from MediaCodecs.
template <>
struct MaxEnumValue<PDMFactory::MediaCodecs> {
static constexpr unsigned int value =
static_cast<unsigned int>(PDMFactory::MediaCodecs::SENTINEL);
};
} // namespace mozilla
#endif /* PDMFactory_h_ */

Просмотреть файл

@ -298,6 +298,9 @@ class PlatformDecoderModule {
// Returns nullptr if the decoder can't be created.
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
// CreateVideoDecoder may need to make additional checks if the
// CreateDecoderParams argument is actually supported and return nullptr if
// not to allow for fallback PDMs to be tried.
virtual already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) = 0;
@ -310,6 +313,9 @@ class PlatformDecoderModule {
// COINIT_MULTITHREADED.
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
// CreateAudioDecoder may need to make additional checks if the
// CreateDecoderParams argument is actually supported and return nullptr if
// not to allow for fallback PDMs to be tried.
virtual already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) = 0;
};

Просмотреть файл

@ -37,11 +37,7 @@ static bool IsAvailableInDefault(DecoderType type) {
switch (type) {
#ifdef MOZ_AV1
case DecoderType::AV1:
// We remove support for decoding AV1 here if RDD is enabled so that
// decoding on the content process doesn't accidentally happen in case
// something goes wrong with launching the RDD process.
return StaticPrefs::media_av1_enabled() &&
!StaticPrefs::media_rdd_process_enabled();
return StaticPrefs::media_av1_enabled();
#endif
case DecoderType::Opus:
case DecoderType::Theora:
@ -128,14 +124,21 @@ bool AgnosticDecoderModule::Supports(
already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> m;
if (VPXDecoder::IsVPX(aParams.mConfig.mMimeType)) {
m = new VPXDecoder(aParams);
}
#ifdef MOZ_AV1
// see comment above about AV1 and the RDD process
else if (AOMDecoder::IsAV1(aParams.mConfig.mMimeType)) {
// We remove support for decoding AV1 here if RDD is enabled so that
// decoding on the content process doesn't accidentally happen in case
// something goes wrong with launching the RDD process.
if (StaticPrefs::media_av1_enabled() &&
(!StaticPrefs::media_rdd_process_enabled() || XRE_IsRDDProcess()) &&
AOMDecoder::IsAV1(aParams.mConfig.mMimeType)) {
if (StaticPrefs::media_av1_use_dav1d()) {
m = new DAV1DDecoder(aParams);
} else {
@ -152,6 +155,9 @@ already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateVideoDecoder(
already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> m;
const TrackInfo& config = aParams.mConfig;

Просмотреть файл

@ -54,6 +54,9 @@ nsresult AppleDecoderModule::Startup() {
already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder;
if (IsVideoSupported(aParams.VideoConfig(), aParams.mOptions)) {
decoder = new AppleVTDecoder(aParams.VideoConfig(), aParams.mImageContainer,
@ -64,6 +67,9 @@ already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateVideoDecoder(
already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder = new AppleATDecoder(aParams.AudioConfig());
return decoder.forget();
}

Просмотреть файл

@ -32,6 +32,9 @@ class FFmpegDecoderModule : public PlatformDecoderModule {
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder = new FFmpegVideoDecoder<V>(
mLib, aParams.VideoConfig(), aParams.mKnowsCompositor,
aParams.mImageContainer,
@ -43,6 +46,9 @@ class FFmpegDecoderModule : public PlatformDecoderModule {
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder =
new FFmpegAudioDecoder<V>(mLib, aParams.AudioConfig());
return decoder.forget();

Просмотреть файл

@ -14,6 +14,7 @@
#include "MFTDecoder.h"
#include "MP4Decoder.h"
#include "MediaInfo.h"
#include "PDMFactory.h"
#include "VPXDecoder.h"
#include "WMF.h"
#include "WMFAudioMFTManager.h"
@ -28,6 +29,7 @@
#include "mozilla/mscom/EnsureMTA.h"
#include "nsComponentManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
#include "nsServiceManagerUtils.h"
#include "nsWindowsHelpers.h"
#include "prsystem.h"
@ -94,26 +96,21 @@ static bool CanCreateMFTDecoder(const GUID& aGuid) {
/* static */
void WMFDecoderModule::Init() {
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
bool testForVPx;
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
// should disable DXVA
sDXVAEnabled = !StaticPrefs::media_gpu_process_decoder();
// We need to test for VPX in the content process as the GPUDecoderModule
// directly calls WMFDecoderModule::Supports in the content process.
// This unnecessary requirement will be fixed in bug 1534815.
testForVPx = true;
} else if (XRE_IsGPUProcess() || XRE_IsRDDProcess()) {
// Always allow DXVA in the GPU or RDD process.
testForVPx = sDXVAEnabled = true;
sDXVAEnabled = true;
} else {
// Only allow DXVA in the UI process if we aren't in e10s Firefox
testForVPx = sDXVAEnabled = !mozilla::BrowserTabsRemoteAutostart();
sDXVAEnabled = !mozilla::BrowserTabsRemoteAutostart();
}
sDXVAEnabled = sDXVAEnabled && gfx::gfxVars::CanUseHardwareVideoDecoding();
testForVPx = testForVPx && gfx::gfxVars::CanUseHardwareVideoDecoding();
bool testForVPx = gfx::gfxVars::CanUseHardwareVideoDecoding();
if (testForVPx && StaticPrefs::media_wmf_vp9_enabled_AtStartup()) {
gfx::WMFVPXVideoCrashGuard guard;
if (!guard.Crashed()) {
@ -214,14 +211,44 @@ static bool CanCreateWMFDecoder() {
/* static */
bool WMFDecoderModule::HasH264() {
if (XRE_IsContentProcess()) {
return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::H264);
}
return CanCreateWMFDecoder<CLSID_CMSH264DecoderMFT>();
}
/* static */
bool WMFDecoderModule::HasVP8() {
if (XRE_IsContentProcess()) {
return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::VP8);
}
return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
}
/* static */
bool WMFDecoderModule::HasVP9() {
if (XRE_IsContentProcess()) {
return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::VP9);
}
return sUsableVPXMFT && CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
}
/* static */
bool WMFDecoderModule::HasAAC() {
if (XRE_IsContentProcess()) {
return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::AAC);
}
return CanCreateWMFDecoder<CLSID_CMSAACDecMFT>();
}
/* static */
bool WMFDecoderModule::HasMP3() {
if (XRE_IsContentProcess()) {
return PDMFactory::Supported().contains(PDMFactory::MediaCodecs::MP3);
}
return CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>();
}
bool WMFDecoderModule::SupportsMimeType(
const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType);
@ -269,17 +296,16 @@ bool WMFDecoderModule::Supports(const SupportDecoderParams& aParams,
return true;
}
if (trackInfo.mMimeType.EqualsLiteral("audio/mpeg") &&
!StaticPrefs::media_ffvpx_mp3_enabled() &&
CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>()) {
!StaticPrefs::media_ffvpx_mp3_enabled() && WMFDecoderModule::HasMP3()) {
return true;
}
if (sUsableVPXMFT) {
static const uint32_t VP8_USABLE_BUILD = 16287;
if ((VPXDecoder::IsVP8(trackInfo.mMimeType) &&
IsWindowsBuildOrLater(VP8_USABLE_BUILD)) ||
VPXDecoder::IsVP9(trackInfo.mMimeType)) {
return CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
}
static const uint32_t VP8_USABLE_BUILD = 16287;
if (VPXDecoder::IsVP8(trackInfo.mMimeType) &&
IsWindowsBuildOrLater(VP8_USABLE_BUILD) && WMFDecoderModule::HasVP8()) {
return true;
}
if (VPXDecoder::IsVP9(trackInfo.mMimeType) && WMFDecoderModule::HasVP9()) {
return true;
}
// Some unsupported codec.

Просмотреть файл

@ -40,8 +40,11 @@ class WMFDecoderModule : public PlatformDecoderModule {
// H.264/AAC decoders if the "Platform Update Supplement for Windows Vista"
// is not installed, and Window N and KN variants also require a "Media
// Feature Pack" to be installed. Windows XP doesn't have WMF.
static bool HasAAC();
static bool HasH264();
static bool HasVP8();
static bool HasVP9();
static bool HasAAC();
static bool HasMP3();
private:
virtual ~WMFDecoderModule();

Просмотреть файл

@ -884,8 +884,6 @@ description = legacy sync IPC - please add detailed description
description = legacy sync IPC - please add detailed description
[PRemoteDecoderManager::PRemoteDecoder]
description = See Bug 1505976 - investigate changing to async instead of matching GPU pattern
[PRemoteDecoderManager::Supports]
description = See Bug 1672072 - We will always need a synchronous call in the worse case scenario, follow-up calls will be cached; however it could be made fully asynchronous under some circumstances..
[PRemoteDecoderManager::Readback]
description = legacy sync IPC - please add detailed description
[PBackground::EnsureRDDProcessAndCreateBridge]