mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-23 22:20:04 +00:00
audio_core: hle: mf: address another batch of reviews from @B3N30
This commit is contained in:
parent
6abd7fcdb0
commit
8f591d3b85
@ -4,6 +4,8 @@ add_library(audio_core STATIC
|
|||||||
codec.h
|
codec.h
|
||||||
dsp_interface.cpp
|
dsp_interface.cpp
|
||||||
dsp_interface.h
|
dsp_interface.h
|
||||||
|
hle/adts.h
|
||||||
|
hle/adts_reader.cpp
|
||||||
hle/common.h
|
hle/common.h
|
||||||
hle/decoder.cpp
|
hle/decoder.cpp
|
||||||
hle/decoder.h
|
hle/decoder.h
|
||||||
@ -28,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.cpp>
|
$<$<BOOL:${ENABLE_MF}>:hle/wmf_decoder.cpp hle/wmf_decoder.h hle/wmf_decoder_utils.cpp hle/wmf_decoder_utils.h>
|
||||||
)
|
)
|
||||||
|
|
||||||
create_target_directory_groups(audio_core)
|
create_target_directory_groups(audio_core)
|
||||||
|
@ -17,14 +17,6 @@ struct ADTSData {
|
|||||||
u32 samplerate;
|
u32 samplerate;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ADTSData ADTSData;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
u32 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
|
||||||
u16 mf_get_aac_tag(struct ADTSData input);
|
u16 mf_get_aac_tag(struct ADTSData input);
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "adts.h"
|
#include "adts.h"
|
||||||
|
|
||||||
constexpr std::array<u32, 16> freq_table = {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};
|
||||||
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 parse_adts(char* buffer, struct ADTSData* out) {
|
u32 parse_adts(char* buffer, struct ADTSData* out) {
|
||||||
|
@ -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 (MFDecoderInit(&transform) != 0) {
|
if (!MFDecoderInit(&transform)) {
|
||||||
LOG_CRITICAL(Audio_DSP, "Can't init decoder");
|
LOG_CRITICAL(Audio_DSP, "Can't init decoder");
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ 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;
|
MFOutputState output_status = OK;
|
||||||
char* output_buffer = nullptr;
|
char* output_buffer = nullptr;
|
||||||
DWORD output_len = 0;
|
DWORD output_len = 0;
|
||||||
IMFSample* output = nullptr;
|
IMFSample* output = nullptr;
|
||||||
@ -113,7 +113,7 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
|||||||
output_status = ReceiveSample(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 == OK || output_status == HAVE_MORE_DATA) {
|
||||||
CopySampleToBuffer(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
|
||||||
@ -133,20 +133,21 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in case of "ok" only, just return quickly
|
// in case of "ok" only, just return quickly
|
||||||
if (output_status == 0)
|
if (output_status == OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// for status = 2, reset MF
|
// for status = 2, reset MF
|
||||||
if (output_status == 2) {
|
if (output_status == NEED_RECONFIG) {
|
||||||
Clear();
|
Clear();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for status = 3, try again with new buffer
|
// for status = 3, try again with new buffer
|
||||||
if (output_status == 3)
|
if (output_status == HAVE_MORE_DATA)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return output_status; // return on other status
|
LOG_ERROR(Audio_DSP, "Errors occurred when receiving output: {}", output_status);
|
||||||
|
return -1; // return on other status
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -22,7 +22,7 @@ void ReportError(std::string msg, HRESULT hr) {
|
|||||||
LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr);
|
LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MFCoInit() {
|
bool 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
|
||||||
@ -30,15 +30,15 @@ int MFCoInit() {
|
|||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
// Do you know you can't initialize MF in test mode or safe mode?
|
// Do you know you can't initialize MF in test mode or safe mode?
|
||||||
ReportError("Failed to initialize Media Foundation", hr);
|
ReportError("Failed to initialize Media Foundation", hr);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(Audio_DSP, "Media Foundation activated");
|
LOG_INFO(Audio_DSP, "Media Foundation activated");
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MFDecoderInit(IMFTransform** transform, GUID audio_format) {
|
bool 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;
|
||||||
@ -54,7 +54,7 @@ int MFDecoderInit(IMFTransform** transform, GUID audio_format) {
|
|||||||
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);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
LOG_INFO(Audio_DSP, "Windows(R) Media Foundation found {} suitable decoder(s)", num_activate);
|
LOG_INFO(Audio_DSP, "Windows(R) Media Foundation found {} suitable decoder(s)", num_activate);
|
||||||
for (unsigned int n = 0; n < num_activate; n++) {
|
for (unsigned int n = 0; n < num_activate; n++) {
|
||||||
@ -66,10 +66,10 @@ int MFDecoderInit(IMFTransform** transform, GUID audio_format) {
|
|||||||
if (*transform == nullptr) {
|
if (*transform == nullptr) {
|
||||||
ReportError("Failed to initialize MFT", hr);
|
ReportError("Failed to initialize MFT", hr);
|
||||||
CoTaskMemFree(activate);
|
CoTaskMemFree(activate);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
CoTaskMemFree(activate);
|
CoTaskMemFree(activate);
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFDeInit(IMFTransform** transform) {
|
void MFDeInit(IMFTransform** transform) {
|
||||||
@ -117,8 +117,8 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio
|
|||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, ADTSData adts,
|
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const 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;
|
||||||
|
|
||||||
@ -261,8 +261,7 @@ int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return: 0: okay; 1: needs more sample; 2: needs reconfiguring; 3: more data available
|
MFOutputState ReceiveSample(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 = nullptr;
|
IMFSample* sample = nullptr;
|
||||||
@ -272,14 +271,14 @@ int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_
|
|||||||
|
|
||||||
if (!out_sample) {
|
if (!out_sample) {
|
||||||
ReportError("nullptr 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 FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = transform->GetOutputStreamInfo(out_stream_id, &out_info);
|
hr = transform->GetOutputStreamInfo(out_stream_id, &out_info);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
ReportError("MFT: Failed to get stream info", hr);
|
ReportError("MFT: Failed to get stream info", hr);
|
||||||
return -1;
|
return FATAL_ERROR;
|
||||||
}
|
}
|
||||||
mft_create_sample = (out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
|
mft_create_sample = (out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) ||
|
||||||
(out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
|
(out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES);
|
||||||
@ -293,7 +292,7 @@ int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_
|
|||||||
sample = CreateSample(nullptr, 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 FATAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,12 +308,12 @@ int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_
|
|||||||
|
|
||||||
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
|
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
|
||||||
// Most likely reasons: data corrupted; your actions not expected by MFT
|
// Most likely reasons: data corrupted; your actions not expected by MFT
|
||||||
return 1;
|
return NEED_MORE_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
|
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
|
||||||
ReportError("MFT: stream format changed, re-configuration required", hr);
|
ReportError("MFT: stream format changed, re-configuration required", hr);
|
||||||
return 2;
|
return NEED_RECONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -322,15 +321,15 @@ int ReceiveSample(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
|
// this status is also unreliable but whatever
|
||||||
return 3;
|
return HAVE_MORE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*out_sample == nullptr) {
|
if (*out_sample == nullptr) {
|
||||||
ReportError("MFT: decoding failure", hr);
|
ReportError("MFT: decoding failure", hr);
|
||||||
return -1;
|
return FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
|
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "adts.h"
|
#include "adts.h"
|
||||||
|
|
||||||
|
enum MFOutputState { FATAL_ERROR = -1, OK = 0, NEED_MORE_INPUT, NEED_RECONFIG, HAVE_MORE_DATA };
|
||||||
|
|
||||||
// utility functions
|
// utility functions
|
||||||
template <class T>
|
template <class T>
|
||||||
void SafeRelease(T** ppT) {
|
void SafeRelease(T** ppT) {
|
||||||
@ -31,17 +33,17 @@ void SafeRelease(T** ppT) {
|
|||||||
void ReportError(std::string msg, HRESULT hr);
|
void ReportError(std::string msg, HRESULT hr);
|
||||||
|
|
||||||
// exported functions
|
// exported functions
|
||||||
int MFCoInit();
|
bool MFCoInit();
|
||||||
int MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC);
|
bool MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC);
|
||||||
void MFDeInit(IMFTransform** transform);
|
void MFDeInit(IMFTransform** transform);
|
||||||
IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0);
|
IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0);
|
||||||
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, ADTSData adts,
|
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const 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 DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag);
|
int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag);
|
||||||
bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id,
|
bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id,
|
||||||
GUID audio_format = MFAudioFormat_PCM);
|
GUID audio_format = MFAudioFormat_PCM);
|
||||||
void MFFlush(IMFTransform** transform);
|
void MFFlush(IMFTransform** transform);
|
||||||
int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample);
|
int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample);
|
||||||
int ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample);
|
MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample);
|
||||||
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len);
|
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len);
|
||||||
|
Loading…
Reference in New Issue
Block a user