mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	audio_core: hle: mf: conform to RAII as possible
This commit is contained in:
		
							parent
							
								
									f0e041e27a
								
							
						
					
					
						commit
						6178cc08b7
					
				
					 3 changed files with 38 additions and 59 deletions
				
			
		|  | @ -16,14 +16,12 @@ public: | ||||||
| private: | private: | ||||||
|     std::optional<BinaryResponse> Initalize(const BinaryRequest& request); |     std::optional<BinaryResponse> Initalize(const BinaryRequest& request); | ||||||
| 
 | 
 | ||||||
|     void Clear(); |  | ||||||
| 
 |  | ||||||
|     std::optional<BinaryResponse> Decode(const BinaryRequest& request); |     std::optional<BinaryResponse> Decode(const BinaryRequest& request); | ||||||
| 
 | 
 | ||||||
|     MFOutputState DecodingLoop(ADTSData adts_header, std::array<std::vector<u8>, 2>& out_streams); |     MFOutputState DecodingLoop(ADTSData adts_header, std::array<std::vector<u8>, 2>& out_streams); | ||||||
| 
 | 
 | ||||||
|     bool initialized = false; |     bool transform_initialized = false; | ||||||
|     bool selected = false; |     bool format_selected = false; | ||||||
| 
 | 
 | ||||||
|     Memory::MemorySystem& memory; |     Memory::MemorySystem& memory; | ||||||
| 
 | 
 | ||||||
|  | @ -32,10 +30,35 @@ private: | ||||||
|     DWORD out_stream_id = 0; |     DWORD out_stream_id = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) {} | WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { | ||||||
|  |     HRESULT hr = S_OK; | ||||||
|  |     hr = CoInitialize(NULL); | ||||||
|  |     // 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); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // lite startup is faster and all what we need is included
 | ||||||
|  |     hr = MFStartup(MF_VERSION, MFSTARTUP_LITE); | ||||||
|  |     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); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     LOG_INFO(Audio_DSP, "Media Foundation activated"); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| WMFDecoder::Impl::~Impl() { | WMFDecoder::Impl::~Impl() { | ||||||
|     Clear(); |     if (transform_initialized) { | ||||||
|  |         MFFlush(transform.get()); | ||||||
|  |         // delete the transform object before shutting down MF
 | ||||||
|  |         // otherwise access violation will occur
 | ||||||
|  |         transform.reset(); | ||||||
|  |         MFShutdown(); | ||||||
|  |         CoUninitialize(); | ||||||
|  |     } | ||||||
|  |     transform_initialized = false; | ||||||
|  |     format_selected = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryRequest& request) { | std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryRequest& request) { | ||||||
|  | @ -65,17 +88,13 @@ std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryReque | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& request) { | std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& request) { | ||||||
|     if (!initialized) { |  | ||||||
|         MFCoInit(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     BinaryResponse response; |     BinaryResponse response; | ||||||
|     std::memcpy(&response, &request, sizeof(response)); |     std::memcpy(&response, &request, sizeof(response)); | ||||||
|     response.unknown1 = 0x0; |     response.unknown1 = 0x0; | ||||||
|     transform = MFDecoderInit(); |     transform = MFDecoderInit(); | ||||||
| 
 | 
 | ||||||
|     if (transform == nullptr) { |     if (transform == nullptr) { | ||||||
|         LOG_CRITICAL(Audio_DSP, "Can't init decoder"); |         LOG_CRITICAL(Audio_DSP, "Can't initialize decoder"); | ||||||
|         return response; |         return response; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -89,22 +108,11 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r | ||||||
|         return response; |         return response; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     initialized = true; |     transform_initialized = true; | ||||||
|  |     format_selected = false;  // select format again if application request initialize the DSP
 | ||||||
|     return response; |     return response; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WMFDecoder::Impl::Clear() { |  | ||||||
|     if (initialized) { |  | ||||||
|         MFFlush(transform.get()); |  | ||||||
|         // delete the transform object before shutting down MF
 |  | ||||||
|         // otherwise access violation will occur
 |  | ||||||
|         transform.reset(); |  | ||||||
|         MFDestroy(); |  | ||||||
|     } |  | ||||||
|     initialized = false; |  | ||||||
|     selected = false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||||
|                                              std::array<std::vector<u8>, 2>& out_streams) { |                                              std::array<std::vector<u8>, 2>& out_streams) { | ||||||
|     MFOutputState output_status = MFOutputState::OK; |     MFOutputState output_status = MFOutputState::OK; | ||||||
|  | @ -138,7 +146,7 @@ MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||||
| 
 | 
 | ||||||
|         // for status = 2, reset MF
 |         // for status = 2, reset MF
 | ||||||
|         if (output_status == MFOutputState::NeedReconfig) { |         if (output_status == MFOutputState::NeedReconfig) { | ||||||
|             Clear(); |             format_selected = false; | ||||||
|             return MFOutputState::NeedReconfig; |             return MFOutputState::NeedReconfig; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -164,7 +172,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
|     response.num_channels = 2; |     response.num_channels = 2; | ||||||
|     response.num_samples = 1024; |     response.num_samples = 1024; | ||||||
| 
 | 
 | ||||||
|     if (!initialized) { |     if (!transform_initialized) { | ||||||
|         LOG_DEBUG(Audio_DSP, "Decoder not initialized"); |         LOG_DEBUG(Audio_DSP, "Decoder not initialized"); | ||||||
|         // This is a hack to continue games when decoder failed to initialize
 |         // This is a hack to continue games when decoder failed to initialize
 | ||||||
|         return response; |         return response; | ||||||
|  | @ -190,7 +198,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
| 
 | 
 | ||||||
|     response.num_channels = adts_meta->ADTSHeader.channels; |     response.num_channels = adts_meta->ADTSHeader.channels; | ||||||
| 
 | 
 | ||||||
|     if (!selected) { |     if (!format_selected) { | ||||||
|         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", |         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", | ||||||
|                   adts_meta->ADTSHeader.channels, adts_meta->ADTSHeader.samplerate); |                   adts_meta->ADTSHeader.channels, adts_meta->ADTSHeader.samplerate); | ||||||
|         SelectInputMediaType(transform.get(), in_stream_id, adts_meta->ADTSHeader, |         SelectInputMediaType(transform.get(), in_stream_id, adts_meta->ADTSHeader, | ||||||
|  | @ -200,7 +208,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
|         // cache the result from detect_mediatype and call select_*_mediatype only once
 |         // cache the result from detect_mediatype and call select_*_mediatype only once
 | ||||||
|         // This could increase performance very slightly
 |         // This could increase performance very slightly
 | ||||||
|         transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); |         transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); | ||||||
|         selected = true; |         format_selected = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sample = CreateSample((void*)data, request.size, 1, 0); |     sample = CreateSample((void*)data, request.size, 1, 0); | ||||||
|  | @ -222,8 +230,8 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
|             LOG_ERROR(Audio_DSP, "Errors occurred when receiving output"); |             LOG_ERROR(Audio_DSP, "Errors occurred when receiving output"); | ||||||
|             return response; |             return response; | ||||||
|         } else if (output_status == MFOutputState::NeedReconfig) { |         } else if (output_status == MFOutputState::NeedReconfig) { | ||||||
|             // re-initialize the whole thing to adapt to new parameters
 |             // flush the transform
 | ||||||
|             this->Initalize(request); |             MFFlush(transform.get()); | ||||||
|             // decode again
 |             // decode again
 | ||||||
|             return this->Decode(request); |             return this->Decode(request); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -25,28 +25,6 @@ void ReportError(std::string msg, HRESULT hr) { | ||||||
|     LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr); |     LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MFCoInit() { |  | ||||||
|     HRESULT hr = S_OK; |  | ||||||
|     hr = CoInitialize(NULL); |  | ||||||
|     // 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); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // lite startup is faster and all what we need is included
 |  | ||||||
|     hr = MFStartup(MF_VERSION, MFSTARTUP_LITE); |  | ||||||
|     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); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     LOG_INFO(Audio_DSP, "Media Foundation activated"); |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) { | unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     MFT_REGISTER_TYPE_INFO reg = {0}; |     MFT_REGISTER_TYPE_INFO reg = {0}; | ||||||
|  | @ -84,11 +62,6 @@ unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) { | ||||||
|     return std::move(transform); |     return std::move(transform); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MFDestroy() { |  | ||||||
|     MFShutdown(); |  | ||||||
|     CoUninitialize(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { | unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     unique_mfptr<IMFMediaBuffer> buf; |     unique_mfptr<IMFMediaBuffer> buf; | ||||||
|  |  | ||||||
|  | @ -73,9 +73,7 @@ struct ADTSMeta { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // exported functions
 | // exported functions
 | ||||||
| bool MFCoInit(); |  | ||||||
| unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC); | unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC); | ||||||
| void MFDestroy(); |  | ||||||
| unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1, | unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1, | ||||||
|                                      LONGLONG duration = 0); |                                      LONGLONG duration = 0); | ||||||
| bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, | bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue