From ea8a1f8754b3c783d69d84ea4ec404ee2f33c278 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Mon, 14 Jan 2019 14:27:43 -0700 Subject: [PATCH] Media Foundation Memory Fix * audio_core: hle: mf: more smart pointers * audio_core: hle: mf: fix memory leaks * audio_core: hle: mf: even more smart pointers --- src/audio_core/hle/wmf_decoder.cpp | 17 ++++---- src/audio_core/hle/wmf_decoder_utils.cpp | 53 +++++++++++------------- src/audio_core/hle/wmf_decoder_utils.h | 7 +++- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/audio_core/hle/wmf_decoder.cpp b/src/audio_core/hle/wmf_decoder.cpp index 3cb4ea1b2..2be505e25 100644 --- a/src/audio_core/hle/wmf_decoder.cpp +++ b/src/audio_core/hle/wmf_decoder.cpp @@ -27,7 +27,7 @@ private: Memory::MemorySystem& memory; - std::unique_ptr> transform; + unique_mfptr transform; DWORD in_stream_id = 0; DWORD out_stream_id = 0; }; @@ -108,14 +108,17 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, MFOutputState output_status = OK; char* output_buffer = nullptr; DWORD output_len = 0; - IMFSample* output = nullptr; + DWORD tmp = 0; + // IMFSample* output_tmp = nullptr; + IMFMediaBuffer* mdbuf = nullptr; + unique_mfptr output; while (true) { - output_status = ReceiveSample(transform.get(), out_stream_id, &output); + auto [output_status, output] = ReceiveSample(transform.get(), out_stream_id); // 0 -> okay; 3 -> okay but more data available (buffer too small) if (output_status == OK || output_status == HAVE_MORE_DATA) { - CopySampleToBuffer(output, (void**)&output_buffer, &output_len); + CopySampleToBuffer(output.get(), (void**)&output_buffer, &output_len); // the following was taken from ffmpeg version of the decoder f32 val_f32; @@ -178,7 +181,7 @@ std::optional WMFDecoder::Impl::Decode(const BinaryRequest& requ u8* data = memory.GetFCRAMPointer(request.src_addr - Memory::FCRAM_PADDR); std::array, 2> out_streams; - IMFSample* sample = nullptr; + unique_mfptr sample; ADTSData adts_header; char* aac_tag = (char*)calloc(1, 14); int input_status = 0; @@ -202,11 +205,11 @@ std::optional WMFDecoder::Impl::Decode(const BinaryRequest& requ selected = true; } - sample = CreateSample((void*)data, request.size, 1, 0); + sample.reset(CreateSample((void*)data, request.size, 1, 0)); sample->SetUINT32(MFSampleExtension_CleanPoint, 1); while (true) { - input_status = SendSample(transform.get(), in_stream_id, sample); + input_status = SendSample(transform.get(), in_stream_id, sample.get()); if (DecodingLoop(adts_header, out_streams) < 0) { // if the decode issues are caused by MFT not accepting new samples, try again diff --git a/src/audio_core/hle/wmf_decoder_utils.cpp b/src/audio_core/hle/wmf_decoder_utils.cpp index 8debac9d2..515dc0e5c 100644 --- a/src/audio_core/hle/wmf_decoder_utils.cpp +++ b/src/audio_core/hle/wmf_decoder_utils.cpp @@ -79,7 +79,8 @@ void MFDeInit(IMFTransform* transform) { IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { HRESULT hr = S_OK; - IMFMediaBuffer* buf = nullptr; + IMFMediaBuffer* buf_tmp = nullptr; + unique_mfptr buf; IMFSample* sample = nullptr; hr = MFCreateSample(&sample); @@ -88,11 +89,12 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio return nullptr; } // Yes, the argument for alignment is the actual alignment - 1 - hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf); + hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf_tmp); if (FAILED(hr)) { ReportError("Unable to allocate a memory buffer for sample", hr); return nullptr; } + buf.reset(buf_tmp); if (data) { BYTE* buffer; // lock the MediaBuffer @@ -100,7 +102,7 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio hr = buf->Lock(&buffer, nullptr, nullptr); if (FAILED(hr)) { SafeRelease(&sample); - SafeRelease(&buf); + buf.reset(); return nullptr; } @@ -110,9 +112,8 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio buf->Unlock(); } - sample->AddBuffer(buf); + sample->AddBuffer(buf.get()); hr = sample->SetSampleDuration(duration); - SafeRelease(&buf); return sample; } @@ -260,59 +261,55 @@ int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample return 0; } -MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample) { +std::tuple> ReceiveSample(IMFTransform* transform, + DWORD out_stream_id) { HRESULT hr; MFT_OUTPUT_DATA_BUFFER out_buffers; - IMFSample* sample = nullptr; + IMFSample* sample_tmp = nullptr; MFT_OUTPUT_STREAM_INFO out_info; DWORD status = 0; + unique_mfptr sample; bool mft_create_sample = false; - if (!out_sample) { - ReportError("nullptr pointer passed to receive_sample()", MF_E_SAMPLE_NOT_WRITABLE); - return FATAL_ERROR; - } - hr = transform->GetOutputStreamInfo(out_stream_id, &out_info); if (FAILED(hr)) { ReportError("MFT: Failed to get stream info", hr); - return FATAL_ERROR; + return std::make_tuple(FATAL_ERROR, std::move(sample)); } mft_create_sample = (out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) || (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); while (true) { sample = nullptr; - *out_sample = nullptr; status = 0; if (!mft_create_sample) { - sample = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); - if (!sample) { + sample_tmp = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); + if (!sample_tmp) { ReportError("MFT: Unable to allocate memory for samples", hr); - return FATAL_ERROR; + return std::make_tuple(FATAL_ERROR, std::move(sample)); } + sample.reset(sample_tmp); } out_buffers.dwStreamID = out_stream_id; - out_buffers.pSample = sample; + out_buffers.pSample = sample.get(); hr = transform->ProcessOutput(0, 1, &out_buffers, &status); if (!FAILED(hr)) { - *out_sample = out_buffers.pSample; break; } if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { // Most likely reasons: data corrupted; your actions not expected by MFT - return NEED_MORE_INPUT; + return std::make_tuple(NEED_MORE_INPUT, std::move(sample)); } if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { ReportError("MFT: stream format changed, re-configuration required", hr); - return NEED_RECONFIG; + return std::make_tuple(NEED_RECONFIG, std::move(sample)); } break; @@ -320,19 +317,19 @@ MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSam if (out_buffers.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE) { // this status is also unreliable but whatever - return HAVE_MORE_DATA; + return std::make_tuple(HAVE_MORE_DATA, std::move(sample)); } - if (*out_sample == nullptr) { + if (out_buffers.pSample == nullptr) { ReportError("MFT: decoding failure", hr); - return FATAL_ERROR; + return std::make_tuple(FATAL_ERROR, std::move(sample)); } - return OK; + return std::make_tuple(OK, std::move(sample)); } int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { - std::unique_ptr> buffer; + unique_mfptr buffer; IMFMediaBuffer* tmp; HRESULT hr = S_OK; BYTE* data; @@ -343,14 +340,14 @@ int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { return -1; } - sample->ConvertToContiguousBuffer(&tmp); + hr = sample->ConvertToContiguousBuffer(&tmp); if (FAILED(hr)) { ReportError("Failed to get sample buffer", hr); return -1; } buffer.reset(tmp); - hr = buffer->Lock(&data, nullptr, nullptr); + hr = tmp->Lock(&data, nullptr, nullptr); if (FAILED(hr)) { ReportError("Failed to lock the buffer", hr); return -1; diff --git a/src/audio_core/hle/wmf_decoder_utils.h b/src/audio_core/hle/wmf_decoder_utils.h index 0b27badcf..22d114881 100644 --- a/src/audio_core/hle/wmf_decoder_utils.h +++ b/src/audio_core/hle/wmf_decoder_utils.h @@ -16,6 +16,7 @@ #include #include +#include #include "adts.h" @@ -37,6 +38,9 @@ struct MFRelease { }; }; +template +using unique_mfptr = std::unique_ptr>; + void ReportError(std::string msg, HRESULT hr); // exported functions @@ -52,5 +56,6 @@ bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audio_format = MFAudioFormat_PCM); void MFFlush(IMFTransform* transform); int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample); -MFOutputState ReceiveSample(IMFTransform* transform, DWORD out_stream_id, IMFSample** out_sample); +std::tuple> ReceiveSample(IMFTransform* transform, + DWORD out_stream_id); int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len);