From 3abf599c4f8b04bed4ed67084588204f65a644d0 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 7 Nov 2023 15:57:56 +1100 Subject: [PATCH] Improve memory usage of mad codec - fix leaks - ensure the synth data is always in internal ram --- src/codecs/include/mad.hpp | 6 +++--- src/codecs/mad.cpp | 40 +++++++++++++++----------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/codecs/include/mad.hpp b/src/codecs/include/mad.hpp index 994e989c..813aa86d 100644 --- a/src/codecs/include/mad.hpp +++ b/src/codecs/include/mad.hpp @@ -45,9 +45,9 @@ class MadMp3Decoder : public ICodec { std::shared_ptr input_; SourceBuffer buffer_; - mad_stream* stream_; - mad_frame* frame_; - mad_synth* synth_; + std::unique_ptr stream_; + std::unique_ptr frame_; + std::unique_ptr synth_; int current_sample_; bool is_eof_; diff --git a/src/codecs/mad.cpp b/src/codecs/mad.cpp index d5516e30..247e33bc 100644 --- a/src/codecs/mad.cpp +++ b/src/codecs/mad.cpp @@ -25,37 +25,29 @@ namespace codecs { [[maybe_unused]] static constexpr char kTag[] = "mad"; -static constexpr uint32_t kMallocCapsPrefer = - MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT; -static constexpr uint32_t kMallocCapsFallback = - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; +static constexpr uint32_t kMallocCaps = MALLOC_CAP_SPIRAM; MadMp3Decoder::MadMp3Decoder() : input_(), buffer_(), stream_(reinterpret_cast( - heap_caps_malloc_prefer(sizeof(mad_stream), - kMallocCapsPrefer, - kMallocCapsFallback))), + heap_caps_malloc(sizeof(mad_stream), kMallocCaps))), frame_(reinterpret_cast( - heap_caps_malloc_prefer(sizeof(mad_frame), - kMallocCapsPrefer, - kMallocCapsFallback))), + heap_caps_malloc(sizeof(mad_frame), kMallocCaps))), synth_(reinterpret_cast( - heap_caps_malloc_prefer(sizeof(mad_synth), - kMallocCapsPrefer, - kMallocCapsFallback))), + heap_caps_malloc(sizeof(mad_synth), + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT))), current_sample_(-1), is_eof_(false), is_eos_(false) { - mad_stream_init(stream_); - mad_frame_init(frame_); - mad_synth_init(synth_); + mad_stream_init(stream_.get()); + mad_frame_init(frame_.get()); + mad_synth_init(synth_.get()); } MadMp3Decoder::~MadMp3Decoder() { - mad_stream_finish(stream_); - mad_frame_finish(frame_); - mad_synth_finish(synth_); + mad_stream_finish(stream_.get()); + mad_frame_finish(frame_.get()); + mad_synth_finish(synth_.get()); } auto MadMp3Decoder::GetBytesUsed() -> std::size_t { @@ -82,11 +74,11 @@ auto MadMp3Decoder::OpenStream(std::shared_ptr input) eof = buffer_.Refill(input_.get()); buffer_.ConsumeBytes([&](cpp::span buf) -> size_t { - mad_stream_buffer(stream_, + mad_stream_buffer(stream_.get(), reinterpret_cast(buf.data()), buf.size_bytes()); - while (mad_header_decode(&header, stream_) < 0) { + while (mad_header_decode(&header, stream_.get()) < 0) { if (MAD_RECOVERABLE(stream_->error)) { // Recoverable errors are usually malformed parts of the stream. // We can recover from them by just retrying the decode. @@ -142,13 +134,13 @@ auto MadMp3Decoder::DecodeTo(cpp::span output) } buffer_.ConsumeBytes([&](cpp::span buf) -> size_t { - mad_stream_buffer(stream_, + mad_stream_buffer(stream_.get(), reinterpret_cast(buf.data()), buf.size()); // Decode the next frame. To signal errors, this returns -1 and // stashes an error code in the stream structure. - while (mad_frame_decode(frame_, stream_) < 0) { + while (mad_frame_decode(frame_.get(), stream_.get()) < 0) { if (MAD_RECOVERABLE(stream_->error)) { // Recoverable errors are usually malformed parts of the stream. // We can recover from them by just retrying the decode. @@ -168,7 +160,7 @@ auto MadMp3Decoder::DecodeTo(cpp::span output) // We've successfully decoded a frame! Now synthesize samples to write // out. - mad_synth_frame(synth_, frame_); + mad_synth_frame(synth_.get(), frame_.get()); current_sample_ = 0; return GetBytesUsed(); });