mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2024-11-24 02:29:20 +01:00
audio_core: hle: mf: conform to RAII as possible
This commit is contained in:
parent
f0e041e27a
commit
6178cc08b7
@ -16,14 +16,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::optional<BinaryResponse> Initalize(const BinaryRequest& request);
|
std::optional<BinaryResponse> Initalize(const BinaryRequest& request);
|
||||||
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
std::optional<BinaryResponse> Decode(const BinaryRequest& request);
|
std::optional<BinaryResponse> Decode(const BinaryRequest& request);
|
||||||
|
|
||||||
MFOutputState 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 initialized = false;
|
bool transform_initialized = false;
|
||||||
bool selected = false;
|
bool format_selected = false;
|
||||||
|
|
||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
|
|
||||||
@ -32,10 +30,35 @@ private:
|
|||||||
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) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lite startup is faster and all what we need is included
|
||||||
|
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
// Do you know you can't initialize MF in test mode or safe mode?
|
||||||
|
ReportError("Failed to initialize Media Foundation", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Audio_DSP, "Media Foundation activated");
|
||||||
|
}
|
||||||
|
|
||||||
WMFDecoder::Impl::~Impl() {
|
WMFDecoder::Impl::~Impl() {
|
||||||
Clear();
|
if (transform_initialized) {
|
||||||
|
MFFlush(transform.get());
|
||||||
|
// delete the transform object before shutting down MF
|
||||||
|
// otherwise access violation will occur
|
||||||
|
transform.reset();
|
||||||
|
MFShutdown();
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
transform_initialized = false;
|
||||||
|
format_selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryRequest& request) {
|
std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryRequest& request) {
|
||||||
@ -65,17 +88,13 @@ std::optional<BinaryResponse> WMFDecoder::Impl::ProcessRequest(const BinaryReque
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& request) {
|
std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& request) {
|
||||||
if (!initialized) {
|
|
||||||
MFCoInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
BinaryResponse response;
|
BinaryResponse response;
|
||||||
std::memcpy(&response, &request, sizeof(response));
|
std::memcpy(&response, &request, sizeof(response));
|
||||||
response.unknown1 = 0x0;
|
response.unknown1 = 0x0;
|
||||||
transform = MFDecoderInit();
|
transform = MFDecoderInit();
|
||||||
|
|
||||||
if (transform == nullptr) {
|
if (transform == nullptr) {
|
||||||
LOG_CRITICAL(Audio_DSP, "Can't init decoder");
|
LOG_CRITICAL(Audio_DSP, "Can't initialize decoder");
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,22 +108,11 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Initalize(const BinaryRequest& r
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
transform_initialized = true;
|
||||||
|
format_selected = false; // select format again if application request initialize the DSP
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WMFDecoder::Impl::Clear() {
|
|
||||||
if (initialized) {
|
|
||||||
MFFlush(transform.get());
|
|
||||||
// delete the transform object before shutting down MF
|
|
||||||
// otherwise access violation will occur
|
|
||||||
transform.reset();
|
|
||||||
MFDestroy();
|
|
||||||
}
|
|
||||||
initialized = false;
|
|
||||||
selected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@ -138,7 +146,7 @@ MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
|||||||
|
|
||||||
// for status = 2, reset MF
|
// for status = 2, reset MF
|
||||||
if (output_status == MFOutputState::NeedReconfig) {
|
if (output_status == MFOutputState::NeedReconfig) {
|
||||||
Clear();
|
format_selected = false;
|
||||||
return MFOutputState::NeedReconfig;
|
return MFOutputState::NeedReconfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +172,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
|
|||||||
response.num_channels = 2;
|
response.num_channels = 2;
|
||||||
response.num_samples = 1024;
|
response.num_samples = 1024;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!transform_initialized) {
|
||||||
LOG_DEBUG(Audio_DSP, "Decoder not initialized");
|
LOG_DEBUG(Audio_DSP, "Decoder not initialized");
|
||||||
// This is a hack to continue games when decoder failed to initialize
|
// This is a hack to continue games when decoder failed to initialize
|
||||||
return response;
|
return response;
|
||||||
@ -190,7 +198,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
|
|||||||
|
|
||||||
response.num_channels = adts_meta->ADTSHeader.channels;
|
response.num_channels = adts_meta->ADTSHeader.channels;
|
||||||
|
|
||||||
if (!selected) {
|
if (!format_selected) {
|
||||||
LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}",
|
LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}",
|
||||||
adts_meta->ADTSHeader.channels, adts_meta->ADTSHeader.samplerate);
|
adts_meta->ADTSHeader.channels, adts_meta->ADTSHeader.samplerate);
|
||||||
SelectInputMediaType(transform.get(), in_stream_id, adts_meta->ADTSHeader,
|
SelectInputMediaType(transform.get(), in_stream_id, adts_meta->ADTSHeader,
|
||||||
@ -200,7 +208,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
|
|||||||
// 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;
|
format_selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample = CreateSample((void*)data, request.size, 1, 0);
|
sample = CreateSample((void*)data, request.size, 1, 0);
|
||||||
@ -222,8 +230,8 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
|
|||||||
LOG_ERROR(Audio_DSP, "Errors occurred when receiving output");
|
LOG_ERROR(Audio_DSP, "Errors occurred when receiving output");
|
||||||
return response;
|
return response;
|
||||||
} else if (output_status == MFOutputState::NeedReconfig) {
|
} else if (output_status == MFOutputState::NeedReconfig) {
|
||||||
// re-initialize the whole thing to adapt to new parameters
|
// flush the transform
|
||||||
this->Initalize(request);
|
MFFlush(transform.get());
|
||||||
// decode again
|
// decode again
|
||||||
return this->Decode(request);
|
return this->Decode(request);
|
||||||
}
|
}
|
||||||
|
@ -25,28 +25,6 @@ void ReportError(std::string msg, HRESULT hr) {
|
|||||||
LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr);
|
LOG_CRITICAL(Audio_DSP, "{}: {:08x}", msg, hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MFCoInit() {
|
|
||||||
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
|
|
||||||
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
|
||||||
if (hr != S_OK) {
|
|
||||||
// Do you know you can't initialize MF in test mode or safe mode?
|
|
||||||
ReportError("Failed to initialize Media Foundation", hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO(Audio_DSP, "Media Foundation activated");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) {
|
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
MFT_REGISTER_TYPE_INFO reg = {0};
|
MFT_REGISTER_TYPE_INFO reg = {0};
|
||||||
@ -84,11 +62,6 @@ unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format) {
|
|||||||
return std::move(transform);
|
return std::move(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFDestroy() {
|
|
||||||
MFShutdown();
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_mfptr<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;
|
HRESULT hr = S_OK;
|
||||||
unique_mfptr<IMFMediaBuffer> buf;
|
unique_mfptr<IMFMediaBuffer> buf;
|
||||||
|
@ -73,9 +73,7 @@ struct ADTSMeta {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// exported functions
|
// exported functions
|
||||||
bool MFCoInit();
|
|
||||||
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC);
|
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC);
|
||||||
void MFDestroy();
|
|
||||||
unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1,
|
unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1,
|
||||||
LONGLONG duration = 0);
|
LONGLONG duration = 0);
|
||||||
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
|
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
|
||||||
|
Loading…
Reference in New Issue
Block a user