audio_core: hle: mf: conform to RAII as possible

This commit is contained in:
liushuyu 2019-02-13 13:49:41 -07:00
parent f0e041e27a
commit 6178cc08b7
3 changed files with 38 additions and 59 deletions

View file

@ -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);
} }

View file

@ -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;

View file

@ -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,