diff --git a/src/audio_core/hle/decoder.h b/src/audio_core/hle/decoder.h index a551df4eb..7bb5a25f4 100644 --- a/src/audio_core/hle/decoder.h +++ b/src/audio_core/hle/decoder.h @@ -56,6 +56,9 @@ class DecoderBase { public: virtual ~DecoderBase(); virtual std::optional ProcessRequest(const BinaryRequest& request) = 0; + /// Return true if this Decoder can be loaded. Return false if the system cannot create the + /// decoder + virtual bool IsValid() const = 0; }; class NullDecoder final : public DecoderBase { @@ -63,6 +66,9 @@ public: NullDecoder(); ~NullDecoder() override; std::optional ProcessRequest(const BinaryRequest& request) override; + bool IsValid() const override { + return true; + } }; } // namespace AudioCore::HLE diff --git a/src/audio_core/hle/ffmpeg_decoder.cpp b/src/audio_core/hle/ffmpeg_decoder.cpp index 6354f2c3e..061decf13 100644 --- a/src/audio_core/hle/ffmpeg_decoder.cpp +++ b/src/audio_core/hle/ffmpeg_decoder.cpp @@ -12,6 +12,9 @@ public: explicit Impl(Memory::MemorySystem& memory); ~Impl(); std::optional ProcessRequest(const BinaryRequest& request); + bool IsValid() const { + return initalized; + } private: std::optional Initalize(const BinaryRequest& request); @@ -261,4 +264,8 @@ std::optional FFMPEGDecoder::ProcessRequest(const BinaryRequest& return impl->ProcessRequest(request); } +bool FFMPEGDecoder::IsValid() const { + return impl->IsValid(); +} + } // namespace AudioCore::HLE diff --git a/src/audio_core/hle/ffmpeg_decoder.h b/src/audio_core/hle/ffmpeg_decoder.h index 190251543..ee5e8cda7 100644 --- a/src/audio_core/hle/ffmpeg_decoder.h +++ b/src/audio_core/hle/ffmpeg_decoder.h @@ -13,6 +13,7 @@ public: explicit FFMPEGDecoder(Memory::MemorySystem& memory); ~FFMPEGDecoder() override; std::optional ProcessRequest(const BinaryRequest& request) override; + bool IsValid() const override; private: class Impl; diff --git a/src/audio_core/hle/hle.cpp b/src/audio_core/hle/hle.cpp index 0bb7d4413..873d6a72e 100644 --- a/src/audio_core/hle/hle.cpp +++ b/src/audio_core/hle/hle.cpp @@ -87,15 +87,27 @@ DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory) : parent(paren source.SetMemory(memory); } -#ifdef HAVE_MF +#if defined(HAVE_MF) && defined(HAVE_FFMPEG) decoder = std::make_unique(memory); -#elif HAVE_FFMPEG + if (!decoder->IsValid()) { + LOG_WARNING(Audio_DSP, "Unable to load MediaFoundation. Attempting to load FFMPEG instead"); + decoder = std::make_unique(memory); + } +#elif defined(HAVE_MF) + decoder = std::make_unique(memory); +#elif defined(HAVE_FFMPEG) decoder = std::make_unique(memory); #else LOG_WARNING(Audio_DSP, "No decoder found, this could lead to missing audio"); decoder = std::make_unique(); #endif // HAVE_MF + if (!decoder->IsValid()) { + LOG_WARNING(Audio_DSP, + "Unable to load any decoders, this could cause missing audio in some games"); + decoder = std::make_unique(); + } + Core::Timing& timing = Core::System::GetInstance().CoreTiming(); tick_event = timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) { diff --git a/src/audio_core/hle/wmf_decoder.cpp b/src/audio_core/hle/wmf_decoder.cpp index 801ae6ee6..f188e5153 100644 --- a/src/audio_core/hle/wmf_decoder.cpp +++ b/src/audio_core/hle/wmf_decoder.cpp @@ -14,6 +14,9 @@ public: explicit Impl(Memory::MemorySystem& memory); ~Impl(); std::optional ProcessRequest(const BinaryRequest& request); + bool IsValid() const { + return is_valid; + } private: std::optional Initalize(const BinaryRequest& request); @@ -30,6 +33,9 @@ private: unique_mfptr transform; DWORD in_stream_id = 0; DWORD out_stream_id = 0; + bool is_valid = false; + bool mf_started = false; + bool coinited = false; }; WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { @@ -45,6 +51,8 @@ WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { // S_FALSE will be returned when COM has already been initialized if (hr != S_OK && hr != S_FALSE) { ReportError("Failed to start COM components", hr); + } else { + coinited = true; } // lite startup is faster and all what we need is included @@ -52,6 +60,8 @@ WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { if (hr != S_OK) { // Do you know you can't initialize MF in test mode or safe mode? ReportError("Failed to initialize Media Foundation", hr); + } else { + mf_started = true; } LOG_INFO(Audio_DSP, "Media Foundation activated"); @@ -73,6 +83,7 @@ WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { return; } transform_initialized = true; + is_valid = true; } WMFDecoder::Impl::~Impl() { @@ -82,8 +93,12 @@ WMFDecoder::Impl::~Impl() { // otherwise access violation will occur transform.reset(); } - MFDecoder::MFShutdown(); - CoUninitialize(); + if (mf_started) { + MFDecoder::MFShutdown(); + } + if (coinited) { + CoUninitialize(); + } } std::optional WMFDecoder::Impl::ProcessRequest(const BinaryRequest& request) { @@ -121,8 +136,8 @@ std::optional WMFDecoder::Impl::Initalize(const BinaryRequest& r return response; } -MFDecoder::MFOutputState WMFDecoder::Impl::DecodingLoop( - ADTSData adts_header, std::array, 2>& out_streams) { +MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, + std::array, 2>& out_streams) { MFOutputState output_status = MFOutputState::OK; std::optional> output_buffer; unique_mfptr output; @@ -280,4 +295,8 @@ std::optional WMFDecoder::ProcessRequest(const BinaryRequest& re return impl->ProcessRequest(request); } +bool WMFDecoder::IsValid() const { + return impl->IsValid(); +} + } // namespace AudioCore::HLE diff --git a/src/audio_core/hle/wmf_decoder.h b/src/audio_core/hle/wmf_decoder.h index 34e223740..a089f2322 100644 --- a/src/audio_core/hle/wmf_decoder.h +++ b/src/audio_core/hle/wmf_decoder.h @@ -13,6 +13,7 @@ public: explicit WMFDecoder(Memory::MemorySystem& memory); ~WMFDecoder() override; std::optional ProcessRequest(const BinaryRequest& request) override; + bool IsValid() const override; private: class Impl;