summaryrefslogtreecommitdiff
path: root/src/codecs/source_buffer.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-08-10 15:33:00 +1000
committerjacqueline <me@jacqueline.id.au>2023-08-10 15:33:00 +1000
commitd8fc77101dcf80a3643a00b3446dca1e390ce997 (patch)
tree9e03881f3857c7b4c6a0b6e3a062947daecc69d1 /src/codecs/source_buffer.cpp
parent67caeb6e3cda44205ba8fe783274b20dc7ea216e (diff)
downloadtangara-fw-d8fc77101dcf80a3643a00b3446dca1e390ce997.tar.gz
Give codecs complete control of their input files
Diffstat (limited to 'src/codecs/source_buffer.cpp')
-rw-r--r--src/codecs/source_buffer.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/codecs/source_buffer.cpp b/src/codecs/source_buffer.cpp
new file mode 100644
index 00000000..5955523e
--- /dev/null
+++ b/src/codecs/source_buffer.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "source_buffer.hpp"
+#include <sys/_stdint.h>
+
+#include <algorithm>
+#include <cstring>
+
+#include "esp_heap_caps.h"
+#include "esp_log.h"
+
+#include "codec.hpp"
+
+namespace codecs {
+
+static constexpr char kTag[] = "dec_buf";
+static constexpr size_t kBufferSize = 1024 * 8;
+
+SourceBuffer::SourceBuffer()
+ : buffer_(reinterpret_cast<std::byte*>(
+ heap_caps_malloc(kBufferSize, MALLOC_CAP_SPIRAM)),
+ kBufferSize),
+ bytes_in_buffer_(0),
+ offset_of_bytes_(0) {
+ assert(buffer_.data() != nullptr);
+}
+
+SourceBuffer::~SourceBuffer() {
+ free(buffer_.data());
+}
+
+auto SourceBuffer::Refill(IStream* src) -> bool {
+ if (bytes_in_buffer_ == buffer_.size_bytes()) {
+ return false;
+ }
+ bool eof = false;
+ AddBytes([&](cpp::span<std::byte> buf) -> size_t {
+ size_t bytes_read = src->Read(buf);
+ eof = bytes_read == 0;
+ return bytes_read;
+ });
+ return eof;
+}
+
+auto SourceBuffer::AddBytes(std::function<size_t(cpp::span<std::byte>)> writer)
+ -> void {
+ if (offset_of_bytes_ > 0) {
+ std::memmove(buffer_.data(), buffer_.data() + offset_of_bytes_,
+ bytes_in_buffer_);
+ offset_of_bytes_ = 0;
+ }
+ size_t added_bytes = std::invoke(writer, buffer_.subspan(bytes_in_buffer_));
+ assert(bytes_in_buffer_ + added_bytes <= buffer_.size_bytes());
+ bytes_in_buffer_ += added_bytes;
+}
+
+auto SourceBuffer::ConsumeBytes(
+ std::function<size_t(cpp::span<std::byte>)> reader) -> void {
+ size_t bytes_consumed = std::invoke(
+ reader, buffer_.subspan(offset_of_bytes_).first(bytes_in_buffer_));
+ assert(bytes_consumed <= bytes_in_buffer_);
+
+ bytes_in_buffer_ -= bytes_consumed;
+ if (bytes_in_buffer_ == 0) {
+ offset_of_bytes_ = 0;
+ } else {
+ offset_of_bytes_ += bytes_consumed;
+ }
+}
+
+} // namespace codecs