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:${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:${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) | ||||
|  |  | |||
|  | @ -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 | ||||
| #ifndef ADTS_ADT | ||||
| #define ADTS_ADT | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <array> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| struct ADTSData { | ||||
|     bool MPEG2; | ||||
|     uint8_t profile; | ||||
|     uint8_t channels; | ||||
|     uint8_t channel_idx; | ||||
|     uint8_t framecount; | ||||
|     uint8_t samplerate_idx; | ||||
|     uint32_t length; | ||||
|     uint32_t samplerate; | ||||
|     u8 profile; | ||||
|     u8 channels; | ||||
|     u8 channel_idx; | ||||
|     u8 framecount; | ||||
|     u8 samplerate_idx; | ||||
|     u32 length; | ||||
|     u32 samplerate; | ||||
| }; | ||||
| 
 | ||||
| typedef struct ADTSData ADTSData; | ||||
|  | @ -22,10 +22,9 @@ typedef struct ADTSData ADTSData; | |||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #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
 | ||||
| uint16_t mf_get_aac_tag(struct ADTSData input); | ||||
| u16 mf_get_aac_tag(struct ADTSData input); | ||||
| #ifdef __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" | ||||
| 
 | ||||
| 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}; | ||||
| 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) { | ||||
|     uint32_t tmp = 0; | ||||
| u32 parse_adts(char* buffer, struct ADTSData* out) { | ||||
|     u32 tmp = 0; | ||||
| 
 | ||||
|     // sync word 0xfff
 | ||||
|     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
 | ||||
| uint16_t mf_get_aac_tag(struct ADTSData input) { | ||||
|     uint16_t tag = 0; | ||||
| u16 mf_get_aac_tag(struct ADTSData input) { | ||||
|     u16 tag = 0; | ||||
| 
 | ||||
|     tag |= input.profile << 11; | ||||
|     tag |= input.samplerate_idx << 7; | ||||
|  | @ -27,13 +27,13 @@ private: | |||
| 
 | ||||
|     Memory::MemorySystem& memory; | ||||
| 
 | ||||
|     IMFTransform* transform = NULL; | ||||
|     IMFTransform* transform = nullptr; | ||||
|     DWORD in_stream_id = 0; | ||||
|     DWORD out_stream_id = 0; | ||||
| }; | ||||
| 
 | ||||
| WMFDecoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) { | ||||
|     mf_coinit(); | ||||
|     MFCoInit(); | ||||
| } | ||||
| 
 | ||||
| WMFDecoder::Impl::~Impl() = default; | ||||
|  | @ -46,7 +46,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryReque | |||
| 
 | ||||
|     switch (request.cmd) { | ||||
|     case DecoderCommand::Init: { | ||||
|         LOG_INFO(Audio_DSP, "AACDecoder initializing"); | ||||
|         LOG_INFO(Audio_DSP, "WMFDecoder initializing"); | ||||
|         return Initalize(request); | ||||
|     } | ||||
|     case DecoderCommand::Decode: { | ||||
|  | @ -73,7 +73,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r | |||
|     std::memcpy(&response, &request, sizeof(response)); | ||||
|     response.unknown1 = 0x0; | ||||
| 
 | ||||
|     if (mf_decoder_init(&transform) != 0) { | ||||
|     if (MFDecoderInit(&transform) != 0) { | ||||
|         LOG_CRITICAL(Audio_DSP, "Can't init decoder"); | ||||
|         return response; | ||||
|     } | ||||
|  | @ -95,8 +95,8 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r | |||
| 
 | ||||
| void WMFDecoder::Impl::Clear() { | ||||
|     if (initalized) { | ||||
|         mf_flush(&transform); | ||||
|         mf_deinit(&transform); | ||||
|         MFFlush(&transform); | ||||
|         MFDeInit(&transform); | ||||
|     } | ||||
|     initalized = false; | ||||
|     selected = false; | ||||
|  | @ -105,16 +105,16 @@ void WMFDecoder::Impl::Clear() { | |||
| int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, | ||||
|                                    std::array<std::vector<u8>, 2>& out_streams) { | ||||
|     int output_status = 0; | ||||
|     char* output_buffer = NULL; | ||||
|     char* output_buffer = nullptr; | ||||
|     DWORD output_len = 0; | ||||
|     IMFSample* output = NULL; | ||||
|     IMFSample* output = nullptr; | ||||
| 
 | ||||
|     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)
 | ||||
|         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
 | ||||
|             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); | ||||
| 
 | ||||
|     std::array<std::vector<u8>, 2> out_streams; | ||||
|     IMFSample* sample = NULL; | ||||
|     IMFSample* sample = nullptr; | ||||
|     ADTSData adts_header; | ||||
|     char* aac_tag = (char*)calloc(1, 14); | ||||
|     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"); | ||||
|         return response; | ||||
|     } | ||||
|  | @ -187,23 +187,23 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ | |||
|     if (!selected) { | ||||
|         LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", | ||||
|                   adts_header.channels, adts_header.samplerate); | ||||
|         select_input_mediatype(transform, in_stream_id, adts_header, (UINT8*)aac_tag, 14); | ||||
|         select_output_mediatype(transform, out_stream_id); | ||||
|         send_sample(transform, in_stream_id, NULL); | ||||
|         SelectInputMediaType(transform, in_stream_id, adts_header, (UINT8*)aac_tag, 14); | ||||
|         SelectOutputMediaType(transform, out_stream_id); | ||||
|         SendSample(transform, in_stream_id, nullptr); | ||||
|         // cache the result from detect_mediatype and call select_*_mediatype only once
 | ||||
|         // This could increase performance very slightly
 | ||||
|         transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); | ||||
|         selected = true; | ||||
|     } | ||||
| 
 | ||||
|     sample = create_sample((void*)data, request.size, 1, 0); | ||||
|     sample = CreateSample((void*)data, request.size, 1, 0); | ||||
|     sample->SetUINT32(MFSampleExtension_CleanPoint, 1); | ||||
| 
 | ||||
|     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 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
 | ||||
|             // MFT didn't accept the input sample
 | ||||
|             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 "wmf_decoder_utils.h" | ||||
| 
 | ||||
|  | @ -9,17 +12,17 @@ void ReportError(std::string msg, HRESULT hr) { | |||
|     LPSTR err; | ||||
|     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | | ||||
|                       FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
|                   NULL, hr, | ||||
|                   nullptr, hr, | ||||
|                   // hardcode to use en_US because if any user had problems with this
 | ||||
|                   // we can help them w/o translating anything
 | ||||
|                   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&err, 0, NULL); | ||||
|     if (err != NULL) { | ||||
|                   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&err, 0, nullptr); | ||||
|     if (err != nullptr) { | ||||
|         LOG_CRITICAL(Audio_DSP, "{}: {}", msg, err); | ||||
|     } | ||||
|     LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr); | ||||
| } | ||||
| 
 | ||||
| int mf_coinit() { | ||||
| int MFCoInit() { | ||||
|     HRESULT hr = S_OK; | ||||
| 
 | ||||
|     // lite startup is faster and all what we need is included
 | ||||
|  | @ -35,7 +38,7 @@ int mf_coinit() { | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | ||||
| int MFDecoderInit(IMFTransform** transform, GUID audio_format) { | ||||
|     HRESULT hr = S_OK; | ||||
|     MFT_REGISTER_TYPE_INFO reg = {0}; | ||||
|     GUID category = MFT_CATEGORY_AUDIO_DECODER; | ||||
|  | @ -47,7 +50,7 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | |||
| 
 | ||||
|     hr = MFTEnumEx(category, | ||||
|                    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) { | ||||
|         ReportError("Failed to enumerate decoders", hr); | ||||
|         CoTaskMemFree(activate); | ||||
|  | @ -57,10 +60,10 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | |||
|     for (unsigned int n = 0; n < num_activate; n++) { | ||||
|         hr = activate[n]->ActivateObject(IID_IMFTransform, (void**)transform); | ||||
|         if (FAILED(hr)) | ||||
|             *transform = NULL; | ||||
|             *transform = nullptr; | ||||
|         activate[n]->Release(); | ||||
|     } | ||||
|     if (*transform == NULL) { | ||||
|     if (*transform == nullptr) { | ||||
|         ReportError("Failed to initialize MFT", hr); | ||||
|         CoTaskMemFree(activate); | ||||
|         return -1; | ||||
|  | @ -69,37 +72,37 @@ int mf_decoder_init(IMFTransform** transform, GUID audio_format) { | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void mf_deinit(IMFTransform** transform) { | ||||
| void MFDeInit(IMFTransform** transform) { | ||||
|     MFShutdownObject(*transform); | ||||
|     SafeRelease(transform); | ||||
|     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; | ||||
|     IMFMediaBuffer* buf = NULL; | ||||
|     IMFSample* sample = NULL; | ||||
|     IMFMediaBuffer* buf = nullptr; | ||||
|     IMFSample* sample = nullptr; | ||||
| 
 | ||||
|     hr = MFCreateSample(&sample); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Unable to allocate a sample", hr); | ||||
|         return NULL; | ||||
|         return nullptr; | ||||
|     } | ||||
|     // Yes, the argument for alignment is the actual alignment - 1
 | ||||
|     hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Unable to allocate a memory buffer for sample", hr); | ||||
|         return NULL; | ||||
|         return nullptr; | ||||
|     } | ||||
|     if (data) { | ||||
|         BYTE* buffer; | ||||
|         // lock the MediaBuffer
 | ||||
|         // this is actually not a thread-safe lock
 | ||||
|         hr = buf->Lock(&buffer, NULL, NULL); | ||||
|         hr = buf->Lock(&buffer, nullptr, nullptr); | ||||
|         if (FAILED(hr)) { | ||||
|             SafeRelease(&sample); | ||||
|             SafeRelease(&buf); | ||||
|             return NULL; | ||||
|             return nullptr; | ||||
|         } | ||||
| 
 | ||||
|         memcpy(buffer, data, len); | ||||
|  | @ -114,7 +117,7 @@ IMFSample* create_sample(void* data, DWORD len, DWORD alignment, LONGLONG durati | |||
|     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) { | ||||
|     HRESULT hr = S_OK; | ||||
|     IMFMediaType* t; | ||||
|  | @ -124,7 +127,7 @@ int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData a | |||
|     hr = MFCreateMediaType(&t); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Unable to create an empty MediaType", hr); | ||||
|         return -1; | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // 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); | ||||
|     if (FAILED(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; | ||||
|     UINT32 tmp; | ||||
|     IMFMediaType* t; | ||||
|  | @ -166,11 +169,11 @@ int select_output_mediatype(IMFTransform* transform, int out_stream_id, GUID aud | |||
|     for (DWORD i = 0;; i++) { | ||||
|         hr = transform->GetOutputAvailableType(out_stream_id, i, &t); | ||||
|         if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) { | ||||
|             return 0; | ||||
|             return true; | ||||
|         } | ||||
|         if (FAILED(hr)) { | ||||
|             ReportError("failed to get output types for MFT", hr); | ||||
|             return -1; | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         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)) { | ||||
|                 ReportError("failed to set MF_MT_AUDIO_BLOCK_ALIGNMENT for MFT on output stream", | ||||
|                             hr); | ||||
|                 return -1; | ||||
|                 return false; | ||||
|             } | ||||
|             hr = transform->SetOutputType(out_stream_id, t, 0); | ||||
|             if (FAILED(hr)) { | ||||
|                 ReportError("failed to select output types for MFT", hr); | ||||
|                 return -1; | ||||
|                 return false; | ||||
|             } | ||||
|             return 0; | ||||
|             return true; | ||||
|         } else { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         return -1; | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     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) { | ||||
|         return -1; | ||||
|     } | ||||
|  | @ -224,7 +227,7 @@ int detect_mediatype(char* buffer, size_t len, ADTSData* output, char** aac_tag) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mf_flush(IMFTransform** transform) { | ||||
| void MFFlush(IMFTransform** transform) { | ||||
|     HRESULT hr = (*transform)->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("MFT: Flush command failed", hr); | ||||
|  | @ -233,11 +236,9 @@ int mf_flush(IMFTransform** transform) { | |||
|     if (FAILED(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; | ||||
| 
 | ||||
|     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
 | ||||
| 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; | ||||
|     MFT_OUTPUT_DATA_BUFFER out_buffers; | ||||
|     IMFSample* sample = NULL; | ||||
|     IMFSample* sample = nullptr; | ||||
|     MFT_OUTPUT_STREAM_INFO out_info; | ||||
|     DWORD status = 0; | ||||
|     bool mft_create_sample = false; | ||||
| 
 | ||||
|     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; | ||||
|     } | ||||
| 
 | ||||
|  | @ -284,12 +285,12 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | |||
|                         (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); | ||||
| 
 | ||||
|     while (true) { | ||||
|         sample = NULL; | ||||
|         *out_sample = NULL; | ||||
|         sample = nullptr; | ||||
|         *out_sample = nullptr; | ||||
|         status = 0; | ||||
| 
 | ||||
|         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) { | ||||
|                 ReportError("MFT: Unable to allocate memory for samples", hr); | ||||
|                 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) { | ||||
|             // TODO: better handling try again and EOF cases using drain value
 | ||||
|             // Most likely reasons: data corrupted; your actions not expected by MFT
 | ||||
|             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) { | ||||
|         // this status is also unreliable but whatever
 | ||||
|         return 3; | ||||
|     } | ||||
| 
 | ||||
|     // TODO: better handling try again and EOF cases using drain value
 | ||||
|     if (*out_sample == NULL) { | ||||
|     if (*out_sample == nullptr) { | ||||
|         ReportError("MFT: decoding failure", hr); | ||||
|         return -1; | ||||
|     } | ||||
|  | @ -332,7 +333,7 @@ int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len) { | ||||
| int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { | ||||
|     IMFMediaBuffer* buffer; | ||||
|     HRESULT hr = S_OK; | ||||
|     BYTE* data; | ||||
|  | @ -349,7 +350,7 @@ int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len) { | |||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     hr = buffer->Lock(&data, NULL, NULL); | ||||
|     hr = buffer->Lock(&data, nullptr, nullptr); | ||||
|     if (FAILED(hr)) { | ||||
|         ReportError("Failed to lock the buffer", hr); | ||||
|         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 | ||||
| 
 | ||||
| #ifndef MF_DECODER | ||||
| #define MF_DECODER | ||||
| 
 | ||||
| // AAC decoder related APIs are only available with WIN7+
 | ||||
| #define WINVER _WIN32_WINNT_WIN7 | ||||
| 
 | ||||
| #include <assert.h> | ||||
|  | @ -23,26 +24,24 @@ template <class T> | |||
| void SafeRelease(T** ppT) { | ||||
|     if (*ppT) { | ||||
|         (*ppT)->Release(); | ||||
|         *ppT = NULL; | ||||
|         *ppT = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ReportError(std::string msg, HRESULT hr); | ||||
| 
 | ||||
| // exported functions
 | ||||
| int mf_coinit(); | ||||
| int mf_decoder_init(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); | ||||
| void mf_deinit(IMFTransform** transform); | ||||
| IMFSample* create_sample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | ||||
| int select_input_mediatype(IMFTransform* transform, int in_stream_id, ADTSData adts, | ||||
| int MFCoInit(); | ||||
| int MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); | ||||
| void MFDeInit(IMFTransform** transform); | ||||
| IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); | ||||
| bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, ADTSData adts, | ||||
|                            UINT8* user_data, UINT32 user_data_len, | ||||
|                            GUID audio_format = MFAudioFormat_AAC); | ||||
| int detect_mediatype(char* buffer, size_t len, ADTSData* output, char** aac_tag); | ||||
| int select_output_mediatype(IMFTransform* transform, int out_stream_id, | ||||
| int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag); | ||||
| bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, | ||||
|                             GUID audio_format = MFAudioFormat_PCM); | ||||
| int mf_flush(IMFTransform** transform); | ||||
| int send_sample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | ||||
| int receive_sample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample); | ||||
| int copy_sample_to_buffer(IMFSample* sample, void** output, DWORD* len); | ||||
| 
 | ||||
| #endif // MF_DECODER
 | ||||
| void MFFlush(IMFTransform** transform); | ||||
| int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); | ||||
| int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample); | ||||
| int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len); | ||||
|  |  | |||
|  | @ -1,5 +1,12 @@ | |||
| const int fixure_buffer_size = 41; | ||||
| const unsigned char fixure_buffer[41] = { | ||||
| // Copyright 2019 Citra Emulator Project
 | ||||
| // 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, | ||||
|     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}; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| // Copyright 2017 Citra Emulator Project
 | ||||
| // Copyright 2019 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| #if defined(HAVE_MF) || defined(HAVE_FFMPEG) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue