From d8fc77101dcf80a3643a00b3446dca1e390ce997 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 10 Aug 2023 15:33:00 +1000 Subject: Give codecs complete control of their input files --- src/codecs/foxenflac.cpp | 77 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 37 deletions(-) (limited to 'src/codecs/foxenflac.cpp') diff --git a/src/codecs/foxenflac.cpp b/src/codecs/foxenflac.cpp index b676f82a..cc110920 100644 --- a/src/codecs/foxenflac.cpp +++ b/src/codecs/foxenflac.cpp @@ -19,23 +19,34 @@ namespace codecs { static const char kTag[] = "flac"; FoxenFlacDecoder::FoxenFlacDecoder() - : flac_(FX_FLAC_ALLOC(FLAC_MAX_BLOCK_SIZE, 2)) {} + : input_(), buffer_(), flac_(FX_FLAC_ALLOC(FLAC_MAX_BLOCK_SIZE, 2)) {} FoxenFlacDecoder::~FoxenFlacDecoder() { free(flac_); } -auto FoxenFlacDecoder::BeginStream(const cpp::span input) - -> Result { - uint32_t bytes_used = input.size_bytes(); - fx_flac_state_t state = - fx_flac_process(flac_, reinterpret_cast(input.data()), - &bytes_used, NULL, NULL); +auto FoxenFlacDecoder::OpenStream(std::shared_ptr input) + -> cpp::result { + input_ = input; + + bool eof = false; + fx_flac_state_t state; + do { + eof = buffer_.Refill(input_.get()); + buffer_.ConsumeBytes([&](cpp::span buf) -> size_t { + uint32_t bytes_used = buf.size(); + state = + fx_flac_process(flac_, reinterpret_cast(buf.data()), + &bytes_used, NULL, NULL); + return bytes_used; + }); + } while (state != FLAC_END_OF_METADATA && !eof); + if (state != FLAC_END_OF_METADATA) { if (state == FLAC_ERR) { - return {bytes_used, cpp::fail(Error::kMalformedData)}; + return cpp::fail(Error::kMalformedData); } else { - return {bytes_used, cpp::fail(Error::kOutOfInput)}; + return cpp::fail(Error::kOutOfInput); } } @@ -43,14 +54,12 @@ auto FoxenFlacDecoder::BeginStream(const cpp::span input) int64_t fs = fx_flac_get_streaminfo(flac_, FLAC_KEY_SAMPLE_RATE); if (channels == FLAC_INVALID_METADATA_KEY || fs == FLAC_INVALID_METADATA_KEY) { - return {bytes_used, cpp::fail(Error::kMalformedData)}; + return cpp::fail(Error::kMalformedData); } OutputFormat format{ .num_channels = static_cast(channels), .sample_rate_hz = static_cast(fs), - .duration_seconds = {}, - .bits_per_second = {}, }; uint64_t num_samples = fx_flac_get_streaminfo(flac_, FLAC_KEY_N_SAMPLES); @@ -58,38 +67,32 @@ auto FoxenFlacDecoder::BeginStream(const cpp::span input) format.duration_seconds = num_samples / fs; } - return {bytes_used, format}; + return format; } -auto FoxenFlacDecoder::ContinueStream(cpp::span input, - cpp::span output) - -> Result { - cpp::span output_as_samples{ - reinterpret_cast(output.data()), output.size_bytes() / 4}; - uint32_t bytes_read = input.size_bytes(); - uint32_t samples_written = output_as_samples.size(); - - fx_flac_state_t state = - fx_flac_process(flac_, reinterpret_cast(input.data()), - &bytes_read, output_as_samples.data(), &samples_written); - if (state == FLAC_ERR) { - return {bytes_read, cpp::fail(Error::kMalformedData)}; - } +auto FoxenFlacDecoder::DecodeTo(cpp::span output) + -> cpp::result { + bool is_eof = buffer_.Refill(input_.get()); - if (samples_written > 0) { - return {bytes_read, - OutputInfo{.samples_written = samples_written, - .is_finished_writing = state == FLAC_END_OF_FRAME}}; + fx_flac_state_t state; + uint32_t samples_written = output.size(); + + buffer_.ConsumeBytes([&](cpp::span buf) -> size_t { + uint32_t bytes_read = buf.size_bytes(); + state = fx_flac_process(flac_, reinterpret_cast(buf.data()), + &bytes_read, output.data(), &samples_written); + return bytes_read; + }); + if (state == FLAC_ERR) { + return cpp::fail(Error::kMalformedData); } - // No error, but no samples written. We must be out of data. - return {bytes_read, cpp::fail(Error::kOutOfInput)}; + return OutputInfo{.samples_written = samples_written, + .is_stream_finished = samples_written == 0 && is_eof}; } -auto FoxenFlacDecoder::SeekStream(cpp::span input, - std::size_t target_sample) -> Result { - // TODO(jacqueline): Implement me. - return {0, {}}; +auto FoxenFlacDecoder::SeekTo(size_t target) -> cpp::result { + return {}; } } // namespace codecs -- cgit v1.2.3