From be764e4f88f7f756f31e57ca52ed5b392ce7ba78 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Mon, 28 Jan 2019 22:23:57 -0700 Subject: [PATCH] audio_core: hle: mf: multiple fixes... ... more smart pointers and re-arrange code --- src/audio_core/hle/adts.h | 1 - src/audio_core/hle/adts_reader.cpp | 1 + src/audio_core/hle/wmf_decoder.cpp | 18 +++++----- src/audio_core/hle/wmf_decoder_utils.cpp | 42 +++++++++++++----------- src/audio_core/hle/wmf_decoder_utils.h | 10 +----- 5 files changed, 33 insertions(+), 39 deletions(-) diff --git a/src/audio_core/hle/adts.h b/src/audio_core/hle/adts.h index 45d1add1c..d662c221c 100644 --- a/src/audio_core/hle/adts.h +++ b/src/audio_core/hle/adts.h @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #pragma once -#include #include "common/common_types.h" struct ADTSData { diff --git a/src/audio_core/hle/adts_reader.cpp b/src/audio_core/hle/adts_reader.cpp index a2df93125..58201d162 100644 --- a/src/audio_core/hle/adts_reader.cpp +++ b/src/audio_core/hle/adts_reader.cpp @@ -1,6 +1,7 @@ // Copyright 2019 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "adts.h" constexpr std::array freq_table = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, diff --git a/src/audio_core/hle/wmf_decoder.cpp b/src/audio_core/hle/wmf_decoder.cpp index 2be505e25..8aa586b8b 100644 --- a/src/audio_core/hle/wmf_decoder.cpp +++ b/src/audio_core/hle/wmf_decoder.cpp @@ -20,7 +20,7 @@ private: std::optional Decode(const BinaryRequest& request); - int DecodingLoop(ADTSData adts_header, std::array, 2>& out_streams); + MFOutputState DecodingLoop(ADTSData adts_header, std::array, 2>& out_streams); bool initalized = false; bool selected = false; @@ -103,7 +103,7 @@ void WMFDecoder::Impl::Clear() { selected = false; } -int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, +MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, std::array, 2>& out_streams) { MFOutputState output_status = OK; char* output_buffer = nullptr; @@ -138,12 +138,12 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, // in case of "ok" only, just return quickly if (output_status == OK) - return 0; + return OK; // for status = 2, reset MF if (output_status == NEED_RECONFIG) { Clear(); - return -1; + return FATAL_ERROR; } // for status = 3, try again with new buffer @@ -151,12 +151,12 @@ int WMFDecoder::Impl::DecodingLoop(ADTSData adts_header, continue; if (output_status == NEED_MORE_INPUT) // according to MS document, this is not an error (?!) - return 1; + return NEED_MORE_INPUT; - return -1; // return on other status + return FATAL_ERROR; // return on other status } - return -1; + return FATAL_ERROR; } std::optional WMFDecoder::Impl::Decode(const BinaryRequest& request) { @@ -205,13 +205,13 @@ std::optional WMFDecoder::Impl::Decode(const BinaryRequest& requ selected = true; } - sample.reset(CreateSample((void*)data, request.size, 1, 0)); + sample = CreateSample((void*)data, request.size, 1, 0); sample->SetUINT32(MFSampleExtension_CleanPoint, 1); while (true) { input_status = SendSample(transform.get(), in_stream_id, sample.get()); - if (DecodingLoop(adts_header, out_streams) < 0) { + if (DecodingLoop(adts_header, out_streams) == FATAL_ERROR) { // 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 diff --git a/src/audio_core/hle/wmf_decoder_utils.cpp b/src/audio_core/hle/wmf_decoder_utils.cpp index 5c1a3713c..fc6a8a0e8 100644 --- a/src/audio_core/hle/wmf_decoder_utils.cpp +++ b/src/audio_core/hle/wmf_decoder_utils.cpp @@ -77,17 +77,19 @@ void MFDeInit(IMFTransform* transform) { CoUninitialize(); } -IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { +unique_mfptr CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duration) { HRESULT hr = S_OK; IMFMediaBuffer* buf_tmp = nullptr; unique_mfptr buf; - IMFSample* sample = nullptr; + IMFSample* sample_tmp = nullptr; + unique_mfptr sample; - hr = MFCreateSample(&sample); + hr = MFCreateSample(&sample_tmp); if (FAILED(hr)) { ReportError("Unable to allocate a sample", hr); return nullptr; } + sample.reset(sample_tmp); // Yes, the argument for alignment is the actual alignment - 1 hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf_tmp); if (FAILED(hr)) { @@ -101,12 +103,11 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio // this is actually not a thread-safe lock hr = buf->Lock(&buffer, nullptr, nullptr); if (FAILED(hr)) { - SafeRelease(&sample); - buf.reset(); + ReportError("Unable to lock down MediaBuffer", hr); return nullptr; } - memcpy(buffer, data, len); + std::memcpy(buffer, data, len); buf->SetCurrentLength(len); buf->Unlock(); @@ -114,7 +115,11 @@ IMFSample* CreateSample(void* data, DWORD len, DWORD alignment, LONGLONG duratio sample->AddBuffer(buf.get()); hr = sample->SetSampleDuration(duration); - return sample; + if (FAILED(hr)) { + ReportError("Unable to set sample duration, but continuing anyway", hr); + } + + return std::move(sample); } bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, @@ -153,13 +158,15 @@ bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSD bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audio_format) { HRESULT hr = S_OK; UINT32 tmp; - IMFMediaType* t; + IMFMediaType* type; + unique_mfptr t; // If you know what you need and what you are doing, you can specify the condition instead of // searching but it's better to use search since MFT may or may not support your output // parameters for (DWORD i = 0;; i++) { - hr = transform->GetOutputAvailableType(out_stream_id, i, &t); + hr = transform->GetOutputAvailableType(out_stream_id, i, &type); + t.reset(type); if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) { return true; } @@ -180,7 +187,7 @@ bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audi hr); return false; } - hr = transform->SetOutputType(out_stream_id, t, 0); + hr = transform->SetOutputType(out_stream_id, t.get(), 0); if (FAILED(hr)) { ReportError("failed to select output types for MFT", hr); return false; @@ -221,8 +228,8 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag) tag = MFGetAACTag(tmp); aac_tmp[12] |= (tag & 0xff00) >> 8; aac_tmp[13] |= (tag & 0x00ff); - memcpy(*aac_tag, aac_tmp, 14); - memcpy(output, &tmp, sizeof(ADTSData)); + std::memcpy(*aac_tag, aac_tmp, 14); + std::memcpy(output, &tmp, sizeof(ADTSData)); return 0; } @@ -250,8 +257,6 @@ int SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample } // FAILED(hr) } else { hr = transform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); - // ffmpeg: Some MFTs (AC3) will send a frame after each drain command (???), so - // ffmpeg: this is required to make draining actually terminate. if (FAILED(hr)) { ReportError("MFT: Failed to drain when processing input", hr); } @@ -264,7 +269,6 @@ std::tuple> ReceiveSample(IMFTransform* t DWORD out_stream_id) { HRESULT hr; MFT_OUTPUT_DATA_BUFFER out_buffers; - IMFSample* sample_tmp = nullptr; MFT_OUTPUT_STREAM_INFO out_info; DWORD status = 0; unique_mfptr sample; @@ -280,16 +284,14 @@ std::tuple> ReceiveSample(IMFTransform* t (out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); while (true) { - sample = nullptr; status = 0; if (!mft_create_sample) { - sample_tmp = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); - if (!sample_tmp) { + sample = CreateSample(nullptr, out_info.cbSize, out_info.cbAlignment); + if (!sample.get()) { ReportError("MFT: Unable to allocate memory for samples", hr); return std::make_tuple(FATAL_ERROR, std::move(sample)); } - sample.reset(sample_tmp); } out_buffers.dwStreamID = out_stream_id; @@ -353,7 +355,7 @@ int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) { } *output = malloc(*len); - memcpy(*output, data, *len); + std::memcpy(*output, data, *len); // if buffer unlock fails, then... whatever, we have already got data buffer->Unlock(); diff --git a/src/audio_core/hle/wmf_decoder_utils.h b/src/audio_core/hle/wmf_decoder_utils.h index 82b6b1a73..da39319c9 100644 --- a/src/audio_core/hle/wmf_decoder_utils.h +++ b/src/audio_core/hle/wmf_decoder_utils.h @@ -20,14 +20,6 @@ enum MFOutputState { FATAL_ERROR = -1, OK = 0, NEED_MORE_INPUT, NEED_RECONFIG, HAVE_MORE_DATA }; // utility functions -template -void SafeRelease(T** ppT) { - if (*ppT) { - (*ppT)->Release(); - *ppT = nullptr; - } -} - template struct MFRelease { void operator()(T* pointer) const { @@ -44,7 +36,7 @@ void ReportError(std::string msg, HRESULT hr); bool MFCoInit(); bool MFDecoderInit(IMFTransform** transform, GUID audio_format = MFAudioFormat_AAC); void MFDeInit(IMFTransform* transform); -IMFSample* CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); +unique_mfptr CreateSample(void* data, DWORD len, DWORD alignment = 1, LONGLONG duration = 0); bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, UINT8* user_data, UINT32 user_data_len, GUID audio_format = MFAudioFormat_AAC);