summaryrefslogtreecommitdiff
path: root/src/codecs/mad.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-06-22 09:40:46 +1000
committerjacqueline <me@jacqueline.id.au>2023-06-22 09:40:46 +1000
commitcde8002df4a86a2a6efd4aa0b5c174b2f39f7bf7 (patch)
tree58f7281b56539eee5a5b12e981b59349511c3c2c /src/codecs/mad.cpp
parentb58b072d2d42cc1a9dab3e6b27f2f3ae70fe7610 (diff)
downloadtangara-fw-cde8002df4a86a2a6efd4aa0b5c174b2f39f7bf7.tar.gz
Fix (i think?) mysterious overly large reads in libmad
Diffstat (limited to 'src/codecs/mad.cpp')
-rw-r--r--src/codecs/mad.cpp44
1 files changed, 28 insertions, 16 deletions
diff --git a/src/codecs/mad.cpp b/src/codecs/mad.cpp
index f3f3cffe..23b4ccf6 100644
--- a/src/codecs/mad.cpp
+++ b/src/codecs/mad.cpp
@@ -13,6 +13,7 @@
#include "mad.h"
#include "codec.hpp"
+#include "esp_log.h"
#include "result.hpp"
#include "types.hpp"
@@ -43,9 +44,13 @@ MadMp3Decoder::~MadMp3Decoder() {
mad_synth_finish(&synth_);
}
-auto MadMp3Decoder::GetInputPosition() -> std::size_t {
- assert(stream_.next_frame >= stream_.buffer);
- return stream_.next_frame - stream_.buffer;
+auto MadMp3Decoder::GetBytesUsed(std::size_t buffer_size) -> std::size_t {
+ if (stream_.next_frame) {
+ std::size_t remaining = stream_.bufend - stream_.next_frame;
+ return buffer_size - remaining;
+ } else {
+ return stream_.bufend - stream_.buffer;
+ }
}
auto MadMp3Decoder::BeginStream(const cpp::span<const std::byte> input)
@@ -68,13 +73,13 @@ auto MadMp3Decoder::BeginStream(const cpp::span<const std::byte> input)
continue;
}
if (stream_.error == MAD_ERROR_BUFLEN) {
- return {GetInputPosition(), cpp::fail(Error::kOutOfInput)};
+ return {GetBytesUsed(input.size_bytes()), cpp::fail(Error::kOutOfInput)};
}
- return {GetInputPosition(), cpp::fail(Error::kMalformedData)};
+ return {GetBytesUsed(input.size_bytes()), cpp::fail(Error::kMalformedData)};
}
uint8_t channels = MAD_NCHANNELS(&header);
- return {GetInputPosition(),
+ return {GetBytesUsed(input.size_bytes()),
OutputFormat{
.num_channels = channels,
.bits_per_sample = 24, // We always scale to 24 bits
@@ -85,6 +90,7 @@ auto MadMp3Decoder::BeginStream(const cpp::span<const std::byte> input)
auto MadMp3Decoder::ContinueStream(cpp::span<const std::byte> input,
cpp::span<std::byte> output)
-> Result<OutputInfo> {
+ std::size_t bytes_read = 0;
if (current_sample_ < 0) {
mad_stream_buffer(&stream_,
reinterpret_cast<const unsigned char*>(input.data()),
@@ -101,15 +107,18 @@ auto MadMp3Decoder::ContinueStream(cpp::span<const std::byte> input,
if (stream_.error == MAD_ERROR_BUFLEN) {
// The decoder ran out of bytes before it completed a frame. We
// need to return back to the caller to give us more data.
- return {GetInputPosition(), cpp::fail(Error::kOutOfInput)};
+ return {GetBytesUsed(input.size_bytes()),
+ cpp::fail(Error::kOutOfInput)};
}
// The error is unrecoverable. Give up.
- return {GetInputPosition(), cpp::fail(Error::kMalformedData)};
+ return {GetBytesUsed(input.size_bytes()),
+ cpp::fail(Error::kMalformedData)};
}
// We've successfully decoded a frame! Now synthesize samples to write out.
mad_synth_frame(&synth_, &frame_);
current_sample_ = 0;
+ bytes_read = GetBytesUsed(input.size_bytes());
}
size_t output_byte = 0;
@@ -117,8 +126,8 @@ auto MadMp3Decoder::ContinueStream(cpp::span<const std::byte> input,
if (output_byte + (4 * synth_.pcm.channels) >= output.size()) {
// We can't fit the next sample into the buffer. Stop now, and also avoid
// writing the sample for only half the channels.
- return {GetInputPosition(), OutputInfo{.bytes_written = output_byte,
- .is_finished_writing = false}};
+ return {bytes_read, OutputInfo{.bytes_written = output_byte,
+ .is_finished_writing = false}};
}
for (int channel = 0; channel < synth_.pcm.channels; channel++) {
@@ -135,8 +144,8 @@ auto MadMp3Decoder::ContinueStream(cpp::span<const std::byte> input,
// We wrote everything! Reset, ready for the next frame.
current_sample_ = -1;
- return {GetInputPosition(), OutputInfo{.bytes_written = output_byte,
- .is_finished_writing = true}};
+ return {bytes_read, OutputInfo{.bytes_written = output_byte,
+ .is_finished_writing = true}};
}
auto MadMp3Decoder::SeekStream(cpp::span<const std::byte> input,
@@ -160,7 +169,8 @@ auto MadMp3Decoder::SeekStream(cpp::span<const std::byte> input,
} else {
// Don't bother checking for other errors; if the first part of the
// stream doesn't even contain a header then something's gone wrong.
- return {GetInputPosition(), cpp::fail(Error::kMalformedData)};
+ return {GetBytesUsed(input.size_bytes()),
+ cpp::fail(Error::kMalformedData)};
}
}
@@ -184,10 +194,12 @@ auto MadMp3Decoder::SeekStream(cpp::span<const std::byte> input,
continue;
}
if (stream_.error == MAD_ERROR_BUFLEN) {
- return {GetInputPosition(), cpp::fail(Error::kOutOfInput)};
+ return {GetBytesUsed(input.size_bytes()),
+ cpp::fail(Error::kOutOfInput)};
}
// The error is unrecoverable. Give up.
- return {GetInputPosition(), cpp::fail(Error::kMalformedData)};
+ return {GetBytesUsed(input.size_bytes()),
+ cpp::fail(Error::kMalformedData)};
}
if (frames_to_go <= 1) {
@@ -202,7 +214,7 @@ auto MadMp3Decoder::SeekStream(cpp::span<const std::byte> input,
// call.
current_sample_ =
(target_sample > current_sample) ? target_sample - current_sample : 0;
- return {GetInputPosition(), {}};
+ return {GetBytesUsed(input.size_bytes()), {}};
}
}
}