diff options
Diffstat (limited to 'src/codecs/miniflac.cpp')
| -rw-r--r-- | src/codecs/miniflac.cpp | 130 |
1 files changed, 129 insertions, 1 deletions
diff --git a/src/codecs/miniflac.cpp b/src/codecs/miniflac.cpp index d0b40f96..8ec12df5 100644 --- a/src/codecs/miniflac.cpp +++ b/src/codecs/miniflac.cpp @@ -111,6 +111,131 @@ auto MiniFlacDecoder::OpenStream(std::shared_ptr<IStream> input,uint32_t offset) return cpp::fail(Error::kMalformedData); } + // Seeking + offset = 50; + if (offset) { + // TODO: This assumes a constant sample_rate + uint64_t target_sample = sample_rate * offset; + uint32_t num_seekpoints; + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_seektable_seekpoints( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used, &num_seekpoints); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + // TODO: Not having a seektable is not malformed + // but currently seeking will not work without it. + return cpp::fail(Error::kMalformedData); + } + // Loop over the seek table + ESP_LOGI(kTag, "Found seektable with %lu points", num_seekpoints); + uint64_t sample_number; + uint64_t sample_offset_bytes; + uint16_t num_samples_in_target; + for (uint32_t i = 0; i < num_seekpoints; i++) { + // Get sample number + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_seektable_sample_number( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used, &sample_number); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + return cpp::fail(Error::kMalformedData); + } + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_seektable_sample_offset( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used, &sample_offset_bytes); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + return cpp::fail(Error::kMalformedData); + } + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_seektable_samples( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used, &num_samples_in_target); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + return cpp::fail(Error::kMalformedData); + } + + ESP_LOGI(kTag, "Seektable entry %lu", i); + + // Check if we want to seek to this seektable position? + if (sample_number + num_samples_in_target >= target_sample) { + ESP_LOGI(kTag, "Break on Seektable entry %lu", i); + break; + } + } + + // Seek forward to target_sample + if (sample_number > 0) { + ESP_LOGI(kTag, "total samples: %llu", total_samples); + ESP_LOGI(kTag, "TARGET SAMPLE: %llu", target_sample); + ESP_LOGI(kTag, "SAMPLE NUMBER: %llu", sample_number); + } + uint64_t byte_offset = sample_offset_bytes; + ESP_LOGI(kTag, "Byte offset is forward %llu bytes", byte_offset); + ESP_LOGI(kTag, "Decoder state pre: %d", flac_->state); + while(flac_.get()->state == MINIFLAC_METADATA) { + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_sync( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + ESP_LOGI(kTag, "Decoder error 1 %d", res); + } + } + ESP_LOGI(kTag, "Decoder state post: %d", flac_->state); + + + ESP_LOGI(kTag, "Going to skip forward %llu bytes", byte_offset); + if (input_.get()->CanSeek()) { + ESP_LOGI(kTag, "Skipping forward %llu bytes", byte_offset); + buffer_.Empty(); + input_.get()->SeekTo(byte_offset, IStream::SeekFrom::kCurrentPosition); + ESP_LOGI(kTag, "Skipped %llu bytes", byte_offset); + } + + + ESP_LOGI(kTag, "Pre-refill"); + buffer_.Refill(input_.get()); + ESP_LOGI(kTag, "Post-refill"); + + + read_until_result([&](cpp::span<std::byte> buf) -> size_t { + uint32_t bytes_used = 0; + res = miniflac_sync( + flac_.get(), reinterpret_cast<const uint8_t*>(buf.data()), + buf.size_bytes(), &bytes_used); + return bytes_used; + }); + if (res != MINIFLAC_OK) { + ESP_LOGI(kTag, "Decoder error 1 %d", res); + } + ESP_LOGI(kTag, "JOB'S DONE"); + } + + ESP_LOGI(kTag, "Decoder state: %d", flac_->state); + ESP_LOGI(kTag, "Frame header state: %d", flac_->frame.header.state); + + // TODO: Sample number is not guaranteed, could be block index. + ESP_LOGI(kTag, "Ended up... at sample %llu", flac_->frame.header.sample_number); + ESP_LOGI(kTag, "and block index: %lu", flac_->frame.header.frame_number); + ESP_LOGI(kTag, "total samples: %llu", total_samples); + + OutputFormat format{ .num_channels = static_cast<uint8_t>(channels), .sample_rate_hz = static_cast<uint32_t>(sample_rate), @@ -128,6 +253,7 @@ auto MiniFlacDecoder::DecodeTo(cpp::span<sample::Sample> output) MINIFLAC_RESULT res = MINIFLAC_CONTINUE; while (res == MINIFLAC_CONTINUE && !is_eof) { is_eof = buffer_.Refill(input_.get()); + ESP_LOGI(kTag, "EOF? %s", is_eof ? "true" : "false"); buffer_.ConsumeBytes([&](cpp::span<std::byte> buf) -> size_t { // FIXME: We should do a miniflac_sync first, in order to check that // our sample buffers have enough space for the next frame. @@ -147,7 +273,8 @@ auto MiniFlacDecoder::DecodeTo(cpp::span<sample::Sample> output) .is_stream_finished = true, }; } else { - return cpp::fail(Error::kMalformedData); + ESP_LOGI(kTag, "Failed: decoder result: %d", res); + // return cpp::fail(Error::kMalformedData); } } @@ -170,6 +297,7 @@ auto MiniFlacDecoder::DecodeTo(cpp::span<sample::Sample> output) } current_sample_.reset(); + ESP_LOGI(kTag, "Samples written %lu", (uint32_t)samples_written); return OutputInfo{.samples_written = samples_written, .is_stream_finished = samples_written == 0 && is_eof}; } |
