mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	audio_core: hle: mf: multiple fixes...
... more smart pointers and re-arrange code
This commit is contained in:
		
							parent
							
								
									4bc6bfd51f
								
							
						
					
					
						commit
						be764e4f88
					
				
					 5 changed files with 33 additions and 39 deletions
				
			
		|  | @ -3,7 +3,6 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <array> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| struct ADTSData { | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| // Copyright 2019 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| #include <array> | ||||
| #include "adts.h" | ||||
| 
 | ||||
| constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ private: | |||
| 
 | ||||
|     std::optional<BinaryResponse> Decode(const BinaryRequest& request); | ||||
| 
 | ||||
|     int 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 initalized = false; | ||||
|     bool selected = false; | ||||
|  | @ -103,7 +103,7 @@ void WMFDecoder::Impl::Clear() { | |||
|     selected = false; | ||||
| } | ||||
| 
 | ||||
| int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||
| MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||
|                                    std::array<std::vector<u8>, 2>& out_streams) { | ||||
|     MFOutputState output_status = OK; | ||||
|     char* output_buffer = nullptr; | ||||
|  | @ -138,12 +138,12 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | |||
| 
 | ||||
|         // in case of "ok" only, just return quickly
 | ||||
|         if (output_status == OK) | ||||
|             return 0; | ||||
|             return OK; | ||||
| 
 | ||||
|         // for status = 2, reset MF
 | ||||
|         if (output_status == NEED_RECONFIG) { | ||||
|             Clear(); | ||||
|             return -1; | ||||
|             return FATAL_ERROR; | ||||
|         } | ||||
| 
 | ||||
|         // for status = 3, try again with new buffer
 | ||||
|  | @ -151,12 +151,12 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | |||
|             continue; | ||||
| 
 | ||||
|         if (output_status == NEED_MORE_INPUT) // according to MS document, this is not an error (?!)
 | ||||
|             return 1; | ||||
|             return NEED_MORE_INPUT; | ||||
| 
 | ||||
|         return -1; // return on other status
 | ||||
|         return FATAL_ERROR; // return on other status
 | ||||
|     } | ||||
| 
 | ||||
|     return -1; | ||||
|     return FATAL_ERROR; | ||||
| } | ||||
| 
 | ||||
| std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& request) { | ||||
|  | @ -205,13 +205,13 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | |||
|         selected = true; | ||||
|     } | ||||
| 
 | ||||
|     sample.reset(CreateSample((void*)data, request.size, 1, 0)); | ||||
|     sample = CreateSample((void*)data, request.size, 1, 0); | ||||
|     sample->SetUINT32(MFSampleExtension_CleanPoint, 1); | ||||
| 
 | ||||
|     while (true) { | ||||
|         input_status = SendSample(transform.get(), in_stream_id, sample.get()); | ||||
| 
 | ||||
|         if (DecodingLoop(adts_header, out_streams) < 0) { | ||||
|         if (DecodingLoop(adts_header, out_streams) == FATAL_ERROR) { | ||||
|             // if the decode issues are caused by MFT not accepting new samples, try again
 | ||||
|             // NOTICE: you are required to check the output even if you already knew/guessed
 | ||||
|             // MFT didn't accept the input sample
 | ||||
|  |  | |||
|  | @ -77,17 +77,19 @@ void MFDeInit(IMFTransform* transform) { | |||
|     CoUninitialize(); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     IMFMediaBuffer* buf_tmp = nullptr; | ||||
|     unique_mfptr<IMFMediaBuffer> buf; | ||||
|     IMFSample* sample = nullptr; | ||||
|     IMFSample* sample_tmp = nullptr; | ||||
|     unique_mfptr<IMFSample> sample; | ||||
| 
 | ||||
|     hr = MFCreateSample(&sample); | ||||
|     hr = MFCreateSample(&sample_tmp); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Unable to allocate a sample", hr); | ||||
|         return nullptr; | ||||
|     } | ||||
|     sample.reset(sample_tmp); | ||||
|     // Yes, the argument for alignment is the actual alignment - 1
 | ||||
|     hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf_tmp); | ||||
|     if (FAILED(hr)) { | ||||
|  | @ -101,12 +103,11 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio | |||
|         // this is actually not a thread-safe lock
 | ||||
|         hr = buf->Lock(&buffer, nullptr, nullptr); | ||||
|         if (FAILED(hr)) { | ||||
|             SafeRelease(&sample); | ||||
|             buf.reset(); | ||||
|             ReportError("Unable to lock down MediaBuffer", hr); | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         memcpy(buffer, data, len); | ||||
|         std::memcpy(buffer, data, len); | ||||
| 
 | ||||
|         buf->SetCurrentLength(len); | ||||
|         buf->Unlock(); | ||||
|  | @ -114,7 +115,11 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio | |||
| 
 | ||||
|     sample->AddBuffer(buf.get()); | ||||
|     hr = sample->SetSampleDuration(duration); | ||||
|     return sample; | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Unable to set sample duration, but continuing anyway", hr); | ||||
|     } | ||||
| 
 | ||||
|     return std::move(sample); | ||||
| } | ||||
| 
 | ||||
| bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, | ||||
|  | @ -153,13 +158,15 @@ bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSD | |||
| bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audio_format) { | ||||
|     HRESULT hr = S_OK; | ||||
|     UINT32 tmp; | ||||
|     IMFMediaType* t; | ||||
|     IMFMediaType* type; | ||||
|     unique_mfptr<IMFMediaType> t; | ||||
| 
 | ||||
|     // If you know what you need and what you are doing, you can specify the condition instead of
 | ||||
|     // searching but it's better to use search since MFT may or may not support your output
 | ||||
|     // parameters
 | ||||
|     for (DWORD i = 0;; i++) { | ||||
|         hr = transform->GetOutputAvailableType(out_stream_id, i, &t); | ||||
|         hr = transform->GetOutputAvailableType(out_stream_id, i, &type); | ||||
|         t.reset(type); | ||||
|         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) { | ||||
|             return true; | ||||
|         } | ||||
|  | @ -180,7 +187,7 @@ bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audi | |||
|                             hr); | ||||
|                 return false; | ||||
|             } | ||||
|             hr = transform->SetOutputType(out_stream_id, t, 0); | ||||
|             hr = transform->SetOutputType(out_stream_id, t.get(), 0); | ||||
|             if (FAILED(hr)) { | ||||
|                 ReportError("failed to select output types for MFT", hr); | ||||
|                 return false; | ||||
|  | @ -221,8 +228,8 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag) | |||
|     tag = MFGetAACTag(tmp); | ||||
|     aac_tmp[12] |= (tag & 0xff00) >> 8; | ||||
|     aac_tmp[13] |= (tag & 0x00ff); | ||||
|     memcpy(*aac_tag, aac_tmp, 14); | ||||
|     memcpy(output, &tmp, sizeof(ADTSData)); | ||||
|     std::memcpy(*aac_tag, aac_tmp, 14); | ||||
|     std::memcpy(output, &tmp, sizeof(ADTSData)); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -250,8 +257,6 @@ int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample | |||
|         } // FAILED(hr)
 | ||||
|     } else { | ||||
|         hr = transform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); | ||||
|         // ffmpeg: Some MFTs (AC3) will send a frame after each drain command (???), so
 | ||||
|         // ffmpeg: this is required to make draining actually terminate.
 | ||||
|         if (FAILED(hr)) { | ||||
|             ReportError("MFT: Failed to drain when processing input", hr); | ||||
|         } | ||||
|  | @ -264,7 +269,6 @@ std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* t | |||
|                                                                  DWORD out_stream_id) { | ||||
|     HRESULT hr; | ||||
|     MFT_OUTPUT_DATA_BUFFER out_buffers; | ||||
|     IMFSample* sample_tmp = nullptr; | ||||
|     MFT_OUTPUT_STREAM_INFO out_info; | ||||
|     DWORD status = 0; | ||||
|     unique_mfptr<IMFSample> sample; | ||||
|  | @ -280,16 +284,14 @@ std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* t | |||
|                         (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); | ||||
| 
 | ||||
|     while (true) { | ||||
|         sample = nullptr; | ||||
|         status = 0; | ||||
| 
 | ||||
|         if (!mft_create_sample) { | ||||
|             sample_tmp = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); | ||||
|             if (!sample_tmp) { | ||||
|             sample = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); | ||||
|             if (!sample.get()) { | ||||
|                 ReportError("MFT: Unable to allocate memory for samples", hr); | ||||
|                 return std::make_tuple(FATAL_ERROR, std::move(sample)); | ||||
|             } | ||||
|             sample.reset(sample_tmp); | ||||
|         } | ||||
| 
 | ||||
|         out_buffers.dwStreamID = out_stream_id; | ||||
|  | @ -353,7 +355,7 @@ int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { | |||
|     } | ||||
| 
 | ||||
|     *output = malloc(*len); | ||||
|     memcpy(*output, data, *len); | ||||
|     std::memcpy(*output, data, *len); | ||||
| 
 | ||||
|     // if buffer unlock fails, then... whatever, we have already got data
 | ||||
|     buffer->Unlock(); | ||||
|  |  | |||
|  | @ -20,14 +20,6 @@ | |||
| enum MFOutputState { FATAL_ERROR = -1, OK = 0, NEED_MORE_INPUT, NEED_RECONFIG, HAVE_MORE_DATA }; | ||||
| 
 | ||||
| // utility functions
 | ||||
| template <class T> | ||||
| void SafeRelease(T** ppT) { | ||||
|     if (*ppT) { | ||||
|         (*ppT)->Release(); | ||||
|         *ppT = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| template <class T> | ||||
| struct MFRelease { | ||||
|     void operator()(T* pointer) const { | ||||
|  | @ -44,7 +36,7 @@ void ReportError(std::string msg, HRESULT hr); | |||
| bool MFCoInit(); | ||||
| bool MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); | ||||
| void MFDeInit(IMFTransform* transform); | ||||
| IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | ||||
| unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | ||||
| bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, | ||||
|                           UINT8* user_data, UINT32 user_data_len, | ||||
|                           GUID audio_format = MFAudioFormat_AAC); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue