mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	audio_core: hle: mf: return values as std::optional
This commit is contained in:
		
							parent
							
								
									25fa10327b
								
							
						
					
					
						commit
						6332e57069
					
				
					 5 changed files with 44 additions and 34 deletions
				
			
		|  | @ -16,7 +16,7 @@ struct ADTSData { | ||||||
|     u32 samplerate; |     u32 samplerate; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| u32 ParseADTS(char* buffer, ADTSData* out); | ADTSData ParseADTS(char* buffer); | ||||||
| 
 | 
 | ||||||
| // last two bytes of MF AAC decoder user data
 | // last two bytes of MF AAC decoder user data
 | ||||||
| // see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types
 | // see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types
 | ||||||
|  |  | ||||||
|  | @ -8,36 +8,39 @@ constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 3 | ||||||
|                                             16000, 12000, 11025, 8000,  7350,  0,     0,     0}; |                                             16000, 12000, 11025, 8000,  7350,  0,     0,     0}; | ||||||
| constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8}; | constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8}; | ||||||
| 
 | 
 | ||||||
| u32 ParseADTS(char* buffer, ADTSData* out) { | ADTSData ParseADTS(char* buffer) { | ||||||
|     u32 tmp = 0; |     u32 tmp = 0; | ||||||
|  |     ADTSData out; | ||||||
| 
 | 
 | ||||||
|     // sync word 0xfff
 |     // sync word 0xfff
 | ||||||
|     tmp = (buffer[0] << 8) | (buffer[1] & 0xf0); |     tmp = (buffer[0] << 8) | (buffer[1] & 0xf0); | ||||||
|     if ((tmp & 0xffff) != 0xfff0) |     if ((tmp & 0xffff) != 0xfff0) { | ||||||
|         return 0; |         out.length = 0; | ||||||
|     out->MPEG2 = (buffer[1] >> 3) & 0x1; |         return out; | ||||||
|  |     } | ||||||
|  |     out.MPEG2 = (buffer[1] >> 3) & 0x1; | ||||||
|     // bit 17 to 18
 |     // bit 17 to 18
 | ||||||
|     out->profile = (buffer[2] >> 6) + 1; |     out.profile = (buffer[2] >> 6) + 1; | ||||||
|     // bit 19 to 22
 |     // bit 19 to 22
 | ||||||
|     tmp = (buffer[2] >> 2) & 0xf; |     tmp = (buffer[2] >> 2) & 0xf; | ||||||
|     out->samplerate_idx = tmp; |     out.samplerate_idx = tmp; | ||||||
|     out->samplerate = (tmp > 15) ? 0 : freq_table[tmp]; |     out.samplerate = (tmp > 15) ? 0 : freq_table[tmp]; | ||||||
|     // bit 24 to 26
 |     // bit 24 to 26
 | ||||||
|     tmp = ((buffer[2] & 0x1) << 2) | ((buffer[3] >> 6) & 0x3); |     tmp = ((buffer[2] & 0x1) << 2) | ((buffer[3] >> 6) & 0x3); | ||||||
|     out->channel_idx = tmp; |     out.channel_idx = tmp; | ||||||
|     out->channels = (tmp > 7) ? 0 : channel_table[tmp]; |     out.channels = (tmp > 7) ? 0 : channel_table[tmp]; | ||||||
| 
 | 
 | ||||||
|     // bit 55 to 56
 |     // bit 55 to 56
 | ||||||
|     out->framecount = (buffer[6] & 0x3) + 1; |     out.framecount = (buffer[6] & 0x3) + 1; | ||||||
| 
 | 
 | ||||||
|     // bit 31 to 43
 |     // bit 31 to 43
 | ||||||
|     tmp = (buffer[3] & 0x3) << 11; |     tmp = (buffer[3] & 0x3) << 11; | ||||||
|     tmp |= (buffer[4] << 3) & 0x7f8; |     tmp |= (buffer[4] << 3) & 0x7f8; | ||||||
|     tmp |= (buffer[5] >> 5) & 0x7; |     tmp |= (buffer[5] >> 5) & 0x7; | ||||||
| 
 | 
 | ||||||
|     out->length = tmp; |     out.length = tmp; | ||||||
| 
 | 
 | ||||||
|     return tmp; |     return out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // last two bytes of MF AAC decoder user data
 | // last two bytes of MF AAC decoder user data
 | ||||||
|  |  | ||||||
|  | @ -104,8 +104,7 @@ void WMFDecoder::Impl::Clear() { | ||||||
| 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; | ||||||
|     char* output_buffer = nullptr; |     std::optional<std::vector<f32>> output_buffer; | ||||||
|     DWORD output_len = 0; |  | ||||||
|     unique_mfptr<IMFSample> output; |     unique_mfptr<IMFSample> output; | ||||||
| 
 | 
 | ||||||
|     while (true) { |     while (true) { | ||||||
|  | @ -113,22 +112,18 @@ MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||||
| 
 | 
 | ||||||
|         // 0 -> okay; 3 -> okay but more data available (buffer too small)
 |         // 0 -> okay; 3 -> okay but more data available (buffer too small)
 | ||||||
|         if (output_status == MFOutputState::OK || output_status == MFOutputState::HaveMoreData) { |         if (output_status == MFOutputState::OK || output_status == MFOutputState::HaveMoreData) { | ||||||
|             CopySampleToBuffer(output.get(), (void**)&output_buffer, &output_len); |             output_buffer = CopySampleToBuffer(output.get()); | ||||||
| 
 | 
 | ||||||
|             // the following was taken from ffmpeg version of the decoder
 |             // the following was taken from ffmpeg version of the decoder
 | ||||||
|             f32 val_f32; |             f32 val_f32; | ||||||
|             for (size_t i = 0; i < output_len;) { |             for (size_t i = 0; i < output_buffer->size(); i++) { | ||||||
|                 for (std::size_t channel = 0; channel < adts_header.channels; channel++) { |                 for (std::size_t channel = 0; channel < adts_header.channels; channel++) { | ||||||
|                     std::memcpy(&val_f32, output_buffer + i, sizeof(val_f32)); |                     val_f32 = output_buffer->at(i); | ||||||
|                     s16 val = static_cast<s16>(0x7FFF * val_f32); |                     s16 val = static_cast<s16>(0x7FFF * val_f32); | ||||||
|                     out_streams[channel].push_back(val & 0xFF); |                     out_streams[channel].push_back(val & 0xFF); | ||||||
|                     out_streams[channel].push_back(val >> 8); |                     out_streams[channel].push_back(val >> 8); | ||||||
|                     i += sizeof(val_f32); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 |  | ||||||
|             if (output_buffer) |  | ||||||
|                 free(output_buffer); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // in case of "ok" only, just return quickly
 |         // in case of "ok" only, just return quickly
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,12 @@ void ReportError(std::string msg, HRESULT hr) { | ||||||
| 
 | 
 | ||||||
| bool MFCoInit() { | bool MFCoInit() { | ||||||
|     HRESULT hr = S_OK; |     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
 |     // lite startup is faster and all what we need is included
 | ||||||
|     hr = MFStartup(MF_VERSION, MFSTARTUP_LITE); |     hr = MFStartup(MF_VERSION, MFSTARTUP_LITE); | ||||||
|  | @ -216,8 +222,8 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag) | ||||||
|     UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00}; |     UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00}; | ||||||
|     uint16_t tag = 0; |     uint16_t tag = 0; | ||||||
| 
 | 
 | ||||||
|     uint32_t result = ParseADTS(buffer, &tmp); |     tmp = ParseADTS(buffer); | ||||||
|     if (result == 0) { |     if (tmp.length == 0) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -325,33 +331,37 @@ std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* t | ||||||
|     return std::make_tuple(MFOutputState::OK, std::move(sample)); |     return std::make_tuple(MFOutputState::OK, std::move(sample)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { | std::optional<std::vector<f32>> CopySampleToBuffer(IMFSample* sample) { | ||||||
|     unique_mfptr<IMFMediaBuffer> buffer; |     unique_mfptr<IMFMediaBuffer> buffer; | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|  |     std::optional<std::vector<f32>> output; | ||||||
|  |     std::vector<f32> output_buffer; | ||||||
|     BYTE* data; |     BYTE* data; | ||||||
|  |     DWORD len = 0; | ||||||
| 
 | 
 | ||||||
|     hr = sample->GetTotalLength(len); |     hr = sample->GetTotalLength(&len); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Failed to get the length of sample buffer", hr); |         ReportError("Failed to get the length of sample buffer", hr); | ||||||
|         return -1; |         return std::nullopt; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     hr = sample->ConvertToContiguousBuffer(Amp(buffer)); |     hr = sample->ConvertToContiguousBuffer(Amp(buffer)); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Failed to get sample buffer", hr); |         ReportError("Failed to get sample buffer", hr); | ||||||
|         return -1; |         return std::nullopt; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     hr = buffer->Lock(&data, nullptr, nullptr); |     hr = buffer->Lock(&data, nullptr, nullptr); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Failed to lock the buffer", hr); |         ReportError("Failed to lock the buffer", hr); | ||||||
|         return -1; |         return std::nullopt; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     *output = malloc(*len); |     output_buffer.resize(len / sizeof(f32)); | ||||||
|     std::memcpy(*output, data, *len); |     std::memcpy(output_buffer.data(), data, len); | ||||||
|  |     output = output_buffer; | ||||||
| 
 | 
 | ||||||
|     // if buffer unlock fails, then... whatever, we have already got data
 |     // if buffer unlock fails, then... whatever, we have already got data
 | ||||||
|     buffer->Unlock(); |     buffer->Unlock(); | ||||||
|     return 0; |     return output; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,8 +6,10 @@ | ||||||
| // AAC decoder related APIs are only available with WIN7+
 | // AAC decoder related APIs are only available with WIN7+
 | ||||||
| #define WINVER _WIN32_WINNT_WIN7 | #define WINVER _WIN32_WINNT_WIN7 | ||||||
| 
 | 
 | ||||||
|  | #include <optional> | ||||||
| #include <string> | #include <string> | ||||||
| #include <tuple> | #include <tuple> | ||||||
|  | #include <vector> | ||||||
| #include <comdef.h> | #include <comdef.h> | ||||||
| #include <mfapi.h> | #include <mfapi.h> | ||||||
| #include <mferror.h> | #include <mferror.h> | ||||||
|  | @ -45,7 +47,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     SmartPtr& smart_ptr; |     SmartPtr& smart_ptr; | ||||||
|     RawPtr raw_ptr; |     RawPtr raw_ptr = nullptr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename SmartPtr> | template <typename SmartPtr> | ||||||
|  | @ -72,4 +74,4 @@ void MFFlush(IMFTransform* transform); | ||||||
| MFInputState SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | MFInputState SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | ||||||
| std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* transform, | std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* transform, | ||||||
|                                                                  DWORD out_stream_id); |                                                                  DWORD out_stream_id); | ||||||
| int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len); | std::optional<std::vector<f32>> CopySampleToBuffer(IMFSample* sample); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue