mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	audio_core: hle: mf: address reviews from @B3N30
This commit is contained in:
		
							parent
							
								
									11e277149c
								
							
						
					
					
						commit
						7f5b54fda4
					
				
					 8 changed files with 113 additions and 105 deletions
				
			
		|  | @ -30,7 +30,7 @@ add_library(audio_core STATIC | ||||||
|     $<$<BOOL:${SDL2_FOUND}>:sdl2_sink.cpp sdl2_sink.h> |     $<$<BOOL:${SDL2_FOUND}>:sdl2_sink.cpp sdl2_sink.h> | ||||||
|     $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h> |     $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h> | ||||||
|     $<$<BOOL:${FFMPEG_FOUND}>:hle/ffmpeg_decoder.cpp hle/ffmpeg_decoder.h hle/ffmpeg_dl.cpp hle/ffmpeg_dl.h> |     $<$<BOOL:${FFMPEG_FOUND}>:hle/ffmpeg_decoder.cpp hle/ffmpeg_decoder.h hle/ffmpeg_dl.cpp hle/ffmpeg_dl.h> | ||||||
|     $<$<BOOL:${ENABLE_MF}>:hle/wmf_decoder.cpp hle/wmf_decoder.h hle/wmf_decoder_utils.cpp hle/wmf_decoder_utils.h hle/adts_reader.c> |     $<$<BOOL:${ENABLE_MF}>:hle/wmf_decoder.cpp hle/wmf_decoder.h hle/wmf_decoder_utils.cpp hle/wmf_decoder_utils.h hle/adts_reader.cpp> | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| create_target_directory_groups(audio_core) | create_target_directory_groups(audio_core) | ||||||
|  |  | ||||||
|  | @ -1,20 +1,20 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
| #pragma once | #pragma once | ||||||
| #ifndef ADTS_ADT |  | ||||||
| #define ADTS_ADT |  | ||||||
| 
 | 
 | ||||||
| #include <stdbool.h> | #include <array> | ||||||
| #include <stdint.h> | #include "common/common_types.h" | ||||||
| #include <string.h> |  | ||||||
| 
 | 
 | ||||||
| struct ADTSData { | struct ADTSData { | ||||||
|     bool MPEG2; |     bool MPEG2; | ||||||
|     uint8_t profile; |     u8 profile; | ||||||
|     uint8_t channels; |     u8 channels; | ||||||
|     uint8_t channel_idx; |     u8 channel_idx; | ||||||
|     uint8_t framecount; |     u8 framecount; | ||||||
|     uint8_t samplerate_idx; |     u8 samplerate_idx; | ||||||
|     uint32_t length; |     u32 length; | ||||||
|     uint32_t samplerate; |     u32 samplerate; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct ADTSData ADTSData; | typedef struct ADTSData ADTSData; | ||||||
|  | @ -22,10 +22,9 @@ typedef struct ADTSData ADTSData; | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif // __cplusplus
 | #endif // __cplusplus
 | ||||||
| uint32_t parse_adts(char* buffer, struct ADTSData* out); | u32 parse_adts(char* buffer, struct ADTSData* out); | ||||||
| // last two bytes of MF AAC decoder user data
 | // last two bytes of MF AAC decoder user data
 | ||||||
| uint16_t mf_get_aac_tag(struct ADTSData input); | u16 mf_get_aac_tag(struct ADTSData input); | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif // __cplusplus
 | #endif // __cplusplus
 | ||||||
| #endif // ADTS_ADT
 |  | ||||||
|  |  | ||||||
|  | @ -1,12 +1,14 @@ | ||||||
| 
 | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
| #include "adts.h" | #include "adts.h" | ||||||
| 
 | 
 | ||||||
| const uint32_t freq_table[16] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, | constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, | ||||||
|                                  16000, 12000, 11025, 8000,  7350,  0,     0,     0}; |                                  16000, 12000, 11025, 8000,  7350,  0,     0,     0}; | ||||||
| const short channel_table[8] = {0, 1, 2, 3, 4, 5, 6, 8}; | constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8}; | ||||||
| 
 | 
 | ||||||
| uint32_t parse_adts(char* buffer, struct ADTSData* out) { | u32 parse_adts(char* buffer, struct ADTSData* out) { | ||||||
|     uint32_t tmp = 0; |     u32 tmp = 0; | ||||||
| 
 | 
 | ||||||
|     // sync word 0xfff
 |     // sync word 0xfff
 | ||||||
|     tmp = (buffer[0] << 8) | (buffer[1] & 0xf0); |     tmp = (buffer[0] << 8) | (buffer[1] & 0xf0); | ||||||
|  | @ -38,8 +40,8 @@ uint32_t parse_adts(char* buffer, struct ADTSData* out) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // last two bytes of MF AAC decoder user data
 | // last two bytes of MF AAC decoder user data
 | ||||||
| uint16_t mf_get_aac_tag(struct ADTSData input) { | u16 mf_get_aac_tag(struct ADTSData input) { | ||||||
|     uint16_t tag = 0; |     u16 tag = 0; | ||||||
| 
 | 
 | ||||||
|     tag |= input.profile << 11; |     tag |= input.profile << 11; | ||||||
|     tag |= input.samplerate_idx << 7; |     tag |= input.samplerate_idx << 7; | ||||||
|  | @ -27,13 +27,13 @@ private: | ||||||
| 
 | 
 | ||||||
|     Memory::MemorySystem& memory; |     Memory::MemorySystem& memory; | ||||||
| 
 | 
 | ||||||
|     IMFTransform* transform = NULL; |     IMFTransform* transform = nullptr; | ||||||
|     DWORD in_stream_id = 0; |     DWORD in_stream_id = 0; | ||||||
|     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) { | ||||||
|     mf_coinit(); |     MFCoInit(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| WMFDecoder::Impl::~Impl() = default; | WMFDecoder::Impl::~Impl() = default; | ||||||
|  | @ -46,7 +46,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryReque | ||||||
| 
 | 
 | ||||||
|     switch (request.cmd) { |     switch (request.cmd) { | ||||||
|     case DecoderCommand::Init: { |     case DecoderCommand::Init: { | ||||||
|         LOG_INFO(Audio_DSP, "AACDecoder initializing"); |         LOG_INFO(Audio_DSP, "WMFDecoder initializing"); | ||||||
|         return Initalize(request); |         return Initalize(request); | ||||||
|     } |     } | ||||||
|     case DecoderCommand::Decode: { |     case DecoderCommand::Decode: { | ||||||
|  | @ -73,7 +73,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r | ||||||
|     std::memcpy(&response, &request, sizeof(response)); |     std::memcpy(&response, &request, sizeof(response)); | ||||||
|     response.unknown1 = 0x0; |     response.unknown1 = 0x0; | ||||||
| 
 | 
 | ||||||
|     if (mf_decoder_init(&transform) != 0) { |     if (MFDecoderInit(&transform) != 0) { | ||||||
|         LOG_CRITICAL(Audio_DSP, "Can't init decoder"); |         LOG_CRITICAL(Audio_DSP, "Can't init decoder"); | ||||||
|         return response; |         return response; | ||||||
|     } |     } | ||||||
|  | @ -95,8 +95,8 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r | ||||||
| 
 | 
 | ||||||
| void WMFDecoder::Impl::Clear() { | void WMFDecoder::Impl::Clear() { | ||||||
|     if (initalized) { |     if (initalized) { | ||||||
|         mf_flush(&transform); |         MFFlush(&transform); | ||||||
|         mf_deinit(&transform); |         MFDeInit(&transform); | ||||||
|     } |     } | ||||||
|     initalized = false; |     initalized = false; | ||||||
|     selected = false; |     selected = false; | ||||||
|  | @ -105,16 +105,16 @@ void WMFDecoder::Impl::Clear() { | ||||||
| int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||||
|                                    std::array<std::vector<u8>, 2>& out_streams) { |                                    std::array<std::vector<u8>, 2>& out_streams) { | ||||||
|     int output_status = 0; |     int output_status = 0; | ||||||
|     char* output_buffer = NULL; |     char* output_buffer = nullptr; | ||||||
|     DWORD output_len = 0; |     DWORD output_len = 0; | ||||||
|     IMFSample* output = NULL; |     IMFSample* output = nullptr; | ||||||
| 
 | 
 | ||||||
|     while (true) { |     while (true) { | ||||||
|         output_status = receive_sample(transform, out_stream_id, &output); |         output_status = ReceiveSample(transform, out_stream_id, &output); | ||||||
| 
 | 
 | ||||||
|         // 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 == 0 || output_status == 3) { |         if (output_status == 0 || output_status == 3) { | ||||||
|             copy_sample_to_buffer(output, (void**)&output_buffer, &output_len); |             CopySampleToBuffer(output, (void**)&output_buffer, &output_len); | ||||||
| 
 | 
 | ||||||
|             // 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; | ||||||
|  | @ -174,12 +174,12 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
|     u8* data = memory.GetFCRAMPointer(request.src_addr - Memory::FCRAM_PADDR); |     u8* data = memory.GetFCRAMPointer(request.src_addr - Memory::FCRAM_PADDR); | ||||||
| 
 | 
 | ||||||
|     std::array<std::vector<u8>, 2> out_streams; |     std::array<std::vector<u8>, 2> out_streams; | ||||||
|     IMFSample* sample = NULL; |     IMFSample* sample = nullptr; | ||||||
|     ADTSData adts_header; |     ADTSData adts_header; | ||||||
|     char* aac_tag = (char*)calloc(1, 14); |     char* aac_tag = (char*)calloc(1, 14); | ||||||
|     int input_status = 0; |     int input_status = 0; | ||||||
| 
 | 
 | ||||||
|     if (detect_mediatype((char*)data, request.size, &adts_header, &aac_tag) != 0) { |     if (DetectMediaType((char*)data, request.size, &adts_header, &aac_tag) != 0) { | ||||||
|         LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream"); |         LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream"); | ||||||
|         return response; |         return response; | ||||||
|     } |     } | ||||||
|  | @ -187,23 +187,23 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | ||||||
|     if (!selected) { |     if (!selected) { | ||||||
|         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", |         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", | ||||||
|                   adts_header.channels, adts_header.samplerate); |                   adts_header.channels, adts_header.samplerate); | ||||||
|         select_input_mediatype(transform, in_stream_id, adts_header, (UINT8*)aac_tag, 14); |         SelectInputMediaType(transform, in_stream_id, adts_header, (UINT8*)aac_tag, 14); | ||||||
|         select_output_mediatype(transform, out_stream_id); |         SelectOutputMediaType(transform, out_stream_id); | ||||||
|         send_sample(transform, in_stream_id, NULL); |         SendSample(transform, in_stream_id, nullptr); | ||||||
|         // 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; |         selected = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sample = create_sample((void*)data, request.size, 1, 0); |     sample = CreateSample((void*)data, request.size, 1, 0); | ||||||
|     sample->SetUINT32(MFSampleExtension_CleanPoint, 1); |     sample->SetUINT32(MFSampleExtension_CleanPoint, 1); | ||||||
| 
 | 
 | ||||||
|     while (true) { |     while (true) { | ||||||
|         input_status = send_sample(transform, in_stream_id, sample); |         input_status = SendSample(transform, in_stream_id, sample); | ||||||
| 
 | 
 | ||||||
|         if (DecodingLoop(adts_header, out_streams) < 0) { |         if (DecodingLoop(adts_header, out_streams) < 0) { | ||||||
|             // if the decode issues is caused by MFT not accepting new samples, try again
 |             // 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
 |             // NOTICE: you are required to check the output even if you already knew/guessed
 | ||||||
|             // MFT didn't accept the input sample
 |             // MFT didn't accept the input sample
 | ||||||
|             if (input_status == 1) { |             if (input_status == 1) { | ||||||
|  |  | ||||||
|  | @ -1,3 +1,6 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "wmf_decoder_utils.h" | #include "wmf_decoder_utils.h" | ||||||
| 
 | 
 | ||||||
|  | @ -9,17 +12,17 @@ void ReportError(std::string msg, HRESULT hr) { | ||||||
|     LPSTR err; |     LPSTR err; | ||||||
|     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | |     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | | ||||||
|                       FORMAT_MESSAGE_IGNORE_INSERTS, |                       FORMAT_MESSAGE_IGNORE_INSERTS, | ||||||
|                   NULL, hr, |                   nullptr, hr, | ||||||
|                   // hardcode to use en_US because if any user had problems with this
 |                   // hardcode to use en_US because if any user had problems with this
 | ||||||
|                   // we can help them w/o translating anything
 |                   // we can help them w/o translating anything
 | ||||||
|                   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&err, 0, NULL); |                   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&err, 0, nullptr); | ||||||
|     if (err != NULL) { |     if (err != nullptr) { | ||||||
|         LOG_CRITICAL(Audio_DSP, "{}: {}", msg, err); |         LOG_CRITICAL(Audio_DSP, "{}: {}", msg, err); | ||||||
|     } |     } | ||||||
|     LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr); |     LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int mf_coinit() { | int MFCoInit() { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
| 
 | 
 | ||||||
|     // lite startup is faster and all what we need is included
 |     // lite startup is faster and all what we need is included
 | ||||||
|  | @ -35,7 +38,7 @@ int mf_coinit() { | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | int MFDecoderInit(IMFTransform** transform, GUID audio_format) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     MFT_REGISTER_TYPE_INFO reg = {0}; |     MFT_REGISTER_TYPE_INFO reg = {0}; | ||||||
|     GUID category = MFT_CATEGORY_AUDIO_DECODER; |     GUID category = MFT_CATEGORY_AUDIO_DECODER; | ||||||
|  | @ -47,7 +50,7 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | ||||||
| 
 | 
 | ||||||
|     hr = MFTEnumEx(category, |     hr = MFTEnumEx(category, | ||||||
|                    MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER, |                    MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER, | ||||||
|                    ®, NULL, &activate, &num_activate); |                    ®, nullptr, &activate, &num_activate); | ||||||
|     if (FAILED(hr) || num_activate < 1) { |     if (FAILED(hr) || num_activate < 1) { | ||||||
|         ReportError("Failed to enumerate decoders", hr); |         ReportError("Failed to enumerate decoders", hr); | ||||||
|         CoTaskMemFree(activate); |         CoTaskMemFree(activate); | ||||||
|  | @ -57,10 +60,10 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | ||||||
|     for (unsigned int n = 0; n < num_activate; n++) { |     for (unsigned int n = 0; n < num_activate; n++) { | ||||||
|         hr = activate[n]->ActivateObject(IID_IMFTransform, (void**)transform); |         hr = activate[n]->ActivateObject(IID_IMFTransform, (void**)transform); | ||||||
|         if (FAILED(hr)) |         if (FAILED(hr)) | ||||||
|             *transform = NULL; |             *transform = nullptr; | ||||||
|         activate[n]->Release(); |         activate[n]->Release(); | ||||||
|     } |     } | ||||||
|     if (*transform == NULL) { |     if (*transform == nullptr) { | ||||||
|         ReportError("Failed to initialize MFT", hr); |         ReportError("Failed to initialize MFT", hr); | ||||||
|         CoTaskMemFree(activate); |         CoTaskMemFree(activate); | ||||||
|         return -1; |         return -1; | ||||||
|  | @ -69,37 +72,37 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void mf_deinit(IMFTransform** transform) { | void MFDeInit(IMFTransform** transform) { | ||||||
|     MFShutdownObject(*transform); |     MFShutdownObject(*transform); | ||||||
|     SafeRelease(transform); |     SafeRelease(transform); | ||||||
|     CoUninitialize(); |     CoUninitialize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IMFSample* create_sample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { | IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     IMFMediaBuffer* buf = NULL; |     IMFMediaBuffer* buf = nullptr; | ||||||
|     IMFSample* sample = NULL; |     IMFSample* sample = nullptr; | ||||||
| 
 | 
 | ||||||
|     hr = MFCreateSample(&sample); |     hr = MFCreateSample(&sample); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Unable to allocate a sample", hr); |         ReportError("Unable to allocate a sample", hr); | ||||||
|         return NULL; |         return nullptr; | ||||||
|     } |     } | ||||||
|     // Yes, the argument for alignment is the actual alignment - 1
 |     // Yes, the argument for alignment is the actual alignment - 1
 | ||||||
|     hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf); |     hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Unable to allocate a memory buffer for sample", hr); |         ReportError("Unable to allocate a memory buffer for sample", hr); | ||||||
|         return NULL; |         return nullptr; | ||||||
|     } |     } | ||||||
|     if (data) { |     if (data) { | ||||||
|         BYTE* buffer; |         BYTE* buffer; | ||||||
|         // lock the MediaBuffer
 |         // lock the MediaBuffer
 | ||||||
|         // this is actually not a thread-safe lock
 |         // this is actually not a thread-safe lock
 | ||||||
|         hr = buf->Lock(&buffer, NULL, NULL); |         hr = buf->Lock(&buffer, nullptr, nullptr); | ||||||
|         if (FAILED(hr)) { |         if (FAILED(hr)) { | ||||||
|             SafeRelease(&sample); |             SafeRelease(&sample); | ||||||
|             SafeRelease(&buf); |             SafeRelease(&buf); | ||||||
|             return NULL; |             return nullptr; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         memcpy(buffer, data, len); |         memcpy(buffer, data, len); | ||||||
|  | @ -114,7 +117,7 @@ IMFSample* create_sample(void* data, DWORD len, DWORD alignment, LONGLONG durati | ||||||
|     return sample; |     return sample; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData adts, | bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, ADTSData adts, | ||||||
|                            UINT8* user_data, UINT32 user_data_len, GUID audio_format) { |                            UINT8* user_data, UINT32 user_data_len, GUID audio_format) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     IMFMediaType* t; |     IMFMediaType* t; | ||||||
|  | @ -124,7 +127,7 @@ int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData a | ||||||
|     hr = MFCreateMediaType(&t); |     hr = MFCreateMediaType(&t); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Unable to create an empty MediaType", hr); |         ReportError("Unable to create an empty MediaType", hr); | ||||||
|         return -1; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // basic definition
 |     // basic definition
 | ||||||
|  | @ -149,13 +152,13 @@ int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData a | ||||||
|     hr = transform->SetInputType(in_stream_id, t, 0); |     hr = transform->SetInputType(in_stream_id, t, 0); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("failed to select input types for MFT", hr); |         ReportError("failed to select input types for MFT", hr); | ||||||
|         return -1; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int select_output_mediatype(IMFTransform* transform, int out_stream_id, GUID audio_format) { | bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audio_format) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     UINT32 tmp; |     UINT32 tmp; | ||||||
|     IMFMediaType* t; |     IMFMediaType* t; | ||||||
|  | @ -166,11 +169,11 @@ int select_output_mediatype(IMFTransform* transform, int out_stream_id, GUID aud | ||||||
|     for (DWORD i = 0;; i++) { |     for (DWORD i = 0;; i++) { | ||||||
|         hr = transform->GetOutputAvailableType(out_stream_id, i, &t); |         hr = transform->GetOutputAvailableType(out_stream_id, i, &t); | ||||||
|         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) { |         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) { | ||||||
|             return 0; |             return true; | ||||||
|         } |         } | ||||||
|         if (FAILED(hr)) { |         if (FAILED(hr)) { | ||||||
|             ReportError("failed to get output types for MFT", hr); |             ReportError("failed to get output types for MFT", hr); | ||||||
|             return -1; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         hr = t->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &tmp); |         hr = t->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &tmp); | ||||||
|  | @ -183,26 +186,26 @@ int select_output_mediatype(IMFTransform* transform, int out_stream_id, GUID aud | ||||||
|             if (FAILED(hr)) { |             if (FAILED(hr)) { | ||||||
|                 ReportError("failed to set MF_MT_AUDIO_BLOCK_ALIGNMENT for MFT on output stream", |                 ReportError("failed to set MF_MT_AUDIO_BLOCK_ALIGNMENT for MFT on output stream", | ||||||
|                             hr); |                             hr); | ||||||
|                 return -1; |                 return false; | ||||||
|             } |             } | ||||||
|             hr = transform->SetOutputType(out_stream_id, t, 0); |             hr = transform->SetOutputType(out_stream_id, t, 0); | ||||||
|             if (FAILED(hr)) { |             if (FAILED(hr)) { | ||||||
|                 ReportError("failed to select output types for MFT", hr); |                 ReportError("failed to select output types for MFT", hr); | ||||||
|                 return -1; |                 return false; | ||||||
|             } |             } | ||||||
|             return 0; |             return true; | ||||||
|         } else { |         } else { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return -1; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ReportError("MFT: Unable to find preferred output format", E_NOTIMPL); |     ReportError("MFT: Unable to find preferred output format", E_NOTIMPL); | ||||||
|     return -1; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int detect_mediatype(char* buffer, size_t len, ADTSData* output, char** aac_tag) { | int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag) { | ||||||
|     if (len < 7) { |     if (len < 7) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | @ -224,7 +227,7 @@ int detect_mediatype(char* buffer, size_t len, ADTSData* output, char** aac_tag) | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int mf_flush(IMFTransform** transform) { | void MFFlush(IMFTransform** transform) { | ||||||
|     HRESULT hr = (*transform)->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); |     HRESULT hr = (*transform)->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("MFT: Flush command failed", hr); |         ReportError("MFT: Flush command failed", hr); | ||||||
|  | @ -233,11 +236,9 @@ int mf_flush(IMFTransform** transform) { | ||||||
|     if (FAILED(hr)) { |     if (FAILED(hr)) { | ||||||
|         ReportError("Failed to end streaming for MFT", hr); |         ReportError("Failed to end streaming for MFT", hr); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int send_sample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample) { | int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample) { | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
| 
 | 
 | ||||||
|     if (in_sample) { |     if (in_sample) { | ||||||
|  | @ -261,16 +262,16 @@ int send_sample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sampl | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // return: 0: okay; 1: needs more sample; 2: needs reconfiguring; 3: more data available
 | // return: 0: okay; 1: needs more sample; 2: needs reconfiguring; 3: more data available
 | ||||||
| int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample) { | int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample) { | ||||||
|     HRESULT hr; |     HRESULT hr; | ||||||
|     MFT_OUTPUT_DATA_BUFFER out_buffers; |     MFT_OUTPUT_DATA_BUFFER out_buffers; | ||||||
|     IMFSample* sample = NULL; |     IMFSample* sample = nullptr; | ||||||
|     MFT_OUTPUT_STREAM_INFO out_info; |     MFT_OUTPUT_STREAM_INFO out_info; | ||||||
|     DWORD status = 0; |     DWORD status = 0; | ||||||
|     bool mft_create_sample = false; |     bool mft_create_sample = false; | ||||||
| 
 | 
 | ||||||
|     if (!out_sample) { |     if (!out_sample) { | ||||||
|         ReportError("NULL pointer passed to receive_sample()", MF_E_SAMPLE_NOT_WRITABLE); |         ReportError("nullptr pointer passed to receive_sample()", MF_E_SAMPLE_NOT_WRITABLE); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -284,12 +285,12 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | ||||||
|                         (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); |                         (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); | ||||||
| 
 | 
 | ||||||
|     while (true) { |     while (true) { | ||||||
|         sample = NULL; |         sample = nullptr; | ||||||
|         *out_sample = NULL; |         *out_sample = nullptr; | ||||||
|         status = 0; |         status = 0; | ||||||
| 
 | 
 | ||||||
|         if (!mft_create_sample) { |         if (!mft_create_sample) { | ||||||
|             sample = create_sample(NULL, out_info.cbSize, out_info.cbAlignment); |             sample = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); | ||||||
|             if (!sample) { |             if (!sample) { | ||||||
|                 ReportError("MFT: Unable to allocate memory for samples", hr); |                 ReportError("MFT: Unable to allocate memory for samples", hr); | ||||||
|                 return -1; |                 return -1; | ||||||
|  | @ -307,7 +308,7 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { |         if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { | ||||||
|             // TODO: better handling try again and EOF cases using drain value
 |             // Most likely reasons: data corrupted; your actions not expected by MFT
 | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -320,11 +321,11 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (out_buffers.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE) { |     if (out_buffers.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE) { | ||||||
|  |         // this status is also unreliable but whatever
 | ||||||
|         return 3; |         return 3; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO: better handling try again and EOF cases using drain value
 |     if (*out_sample == nullptr) { | ||||||
|     if (*out_sample == NULL) { |  | ||||||
|         ReportError("MFT: decoding failure", hr); |         ReportError("MFT: decoding failure", hr); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | @ -332,7 +333,7 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len) { | int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { | ||||||
|     IMFMediaBuffer* buffer; |     IMFMediaBuffer* buffer; | ||||||
|     HRESULT hr = S_OK; |     HRESULT hr = S_OK; | ||||||
|     BYTE* data; |     BYTE* data; | ||||||
|  | @ -349,7 +350,7 @@ int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     hr = buffer->Lock(&data, NULL, NULL); |     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); | ||||||
|         SafeRelease(&buffer); |         SafeRelease(&buffer); | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #ifndef MF_DECODER | // AAC decoder related APIs are only available with WIN7+
 | ||||||
| #define MF_DECODER |  | ||||||
| 
 |  | ||||||
| #define WINVER _WIN32_WINNT_WIN7 | #define WINVER _WIN32_WINNT_WIN7 | ||||||
| 
 | 
 | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | @ -23,26 +24,24 @@ template <class T> | ||||||
| void SafeRelease(T** ppT) { | void SafeRelease(T** ppT) { | ||||||
|     if (*ppT) { |     if (*ppT) { | ||||||
|         (*ppT)->Release(); |         (*ppT)->Release(); | ||||||
|         *ppT = NULL; |         *ppT = nullptr; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ReportError(std::string msg, HRESULT hr); | void ReportError(std::string msg, HRESULT hr); | ||||||
| 
 | 
 | ||||||
| // exported functions
 | // exported functions
 | ||||||
| int mf_coinit(); | int MFCoInit(); | ||||||
| int mf_decoder_init(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); | int MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); | ||||||
| void mf_deinit(IMFTransform** transform); | void MFDeInit(IMFTransform** transform); | ||||||
| IMFSample* create_sample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | ||||||
| int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData adts, | bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, ADTSData adts, | ||||||
|                            UINT8* user_data, UINT32 user_data_len, |                            UINT8* user_data, UINT32 user_data_len, | ||||||
|                            GUID audio_format = MFAudioFormat_AAC); |                            GUID audio_format = MFAudioFormat_AAC); | ||||||
| int detect_mediatype(char* buffer, size_t len, ADTSData* output, char** aac_tag); | int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag); | ||||||
| int select_output_mediatype(IMFTransform* transform, int out_stream_id, | bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, | ||||||
|                             GUID audio_format = MFAudioFormat_PCM); |                             GUID audio_format = MFAudioFormat_PCM); | ||||||
| int mf_flush(IMFTransform** transform); | void MFFlush(IMFTransform** transform); | ||||||
| int send_sample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | ||||||
| int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample); | int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample); | ||||||
| int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len); | int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len); | ||||||
| 
 |  | ||||||
| #endif // MF_DECODER
 |  | ||||||
|  |  | ||||||
|  | @ -1,5 +1,12 @@ | ||||||
| const int fixure_buffer_size = 41; | // Copyright 2019 Citra Emulator Project
 | ||||||
| const unsigned char fixure_buffer[41] = { | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include <array> | ||||||
|  | 
 | ||||||
|  | constexpr int fixure_buffer_size = 41; | ||||||
|  | constexpr std::array<u8, 41> fixure_buffer[41] = { | ||||||
|     0xff, 0xf1, 0x4c, 0x80, 0x05, 0x3f, 0xfc, 0x21, 0x1a, 0x4e, 0xb0, 0x00, 0x00, 0x00, |     0xff, 0xf1, 0x4c, 0x80, 0x05, 0x3f, 0xfc, 0x21, 0x1a, 0x4e, 0xb0, 0x00, 0x00, 0x00, | ||||||
|     0x05, 0xfc, 0x4e, 0x1f, 0x08, 0x88, 0x00, 0x00, 0x00, 0xc4, 0x1a, 0x03, 0xfc, 0x9c, |     0x05, 0xfc, 0x4e, 0x1f, 0x08, 0x88, 0x00, 0x00, 0x00, 0xc4, 0x1a, 0x03, 0xfc, 0x9c, | ||||||
|     0x3e, 0x1d, 0x08, 0x84, 0x03, 0xd8, 0x3f, 0xe4, 0xe1, 0x20, 0x00, 0x0b, 0x38}; |     0x3e, 0x1d, 0x08, 0x84, 0x03, 0xd8, 0x3f, 0xe4, 0xe1, 0x20, 0x00, 0x0b, 0x38}; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| // Copyright 2017 Citra Emulator Project
 | // Copyright 2019 Citra Emulator Project
 | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| #if defined(HAVE_MF) || defined(HAVE_FFMPEG) | #if defined(HAVE_MF) || defined(HAVE_FFMPEG) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue