diff --git a/NEWS b/NEWS index 0fac9e169..d27757eb2 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.20.18 (not yet released) +* decoder + - flac: improve seeking precision * fix gapless CUE song transitions ver 0.20.17 (2018/02/11) diff --git a/src/decoder/plugins/FlacCommon.cxx b/src/decoder/plugins/FlacCommon.cxx index 1abd5682e..5dfd8555f 100644 --- a/src/decoder/plugins/FlacCommon.cxx +++ b/src/decoder/plugins/FlacCommon.cxx @@ -24,7 +24,6 @@ #include "config.h" #include "FlacCommon.hxx" #include "FlacMetadata.hxx" -#include "util/ConstBuffer.hxx" #include "Log.hxx" #include @@ -143,25 +142,10 @@ FlacDecoder::OnWrite(const FLAC__Frame &frame, if (!initialized && !OnFirstFrame(frame.header)) return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - const auto data = pcm_import.Import(buf, frame.header.blocksize); + chunk = pcm_import.Import(buf, frame.header.blocksize); - unsigned bit_rate = nbytes * 8 * frame.header.sample_rate / + kbit_rate = nbytes * 8 * frame.header.sample_rate / (1000 * frame.header.blocksize); - auto cmd = GetClient()->SubmitData(GetInputStream(), - data.data, data.size, - bit_rate); - switch (cmd) { - case DecoderCommand::NONE: - case DecoderCommand::START: - break; - - case DecoderCommand::STOP: - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - - case DecoderCommand::SEEK: - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } diff --git a/src/decoder/plugins/FlacCommon.hxx b/src/decoder/plugins/FlacCommon.hxx index c33ca6e47..5f8c21b5e 100644 --- a/src/decoder/plugins/FlacCommon.hxx +++ b/src/decoder/plugins/FlacCommon.hxx @@ -27,6 +27,7 @@ #include "FlacInput.hxx" #include "FlacPcm.hxx" #include "../DecoderAPI.hxx" +#include "util/ConstBuffer.hxx" #include @@ -41,6 +42,12 @@ struct FlacDecoder : public FlacInput { */ bool unsupported = false; + /** + * The kbit_rate parameter for the next + * DecoderBridge::SubmitData() call. + */ + uint16_t kbit_rate; + FlacPcmImport pcm_import; /** @@ -51,6 +58,13 @@ struct FlacDecoder : public FlacInput { Tag tag; + /** + * Decoded PCM data obtained by our libFLAC write callback. + * If this is non-empty, then DecoderBridge::SubmitData() + * should be called. + */ + ConstBuffer chunk = nullptr; + FlacDecoder(DecoderClient &_client, InputStream &_input_stream) :FlacInput(_input_stream, &_client) {} diff --git a/src/decoder/plugins/FlacDecoderPlugin.cxx b/src/decoder/plugins/FlacDecoderPlugin.cxx index 0b1c2a12a..80647d07a 100644 --- a/src/decoder/plugins/FlacDecoderPlugin.cxx +++ b/src/decoder/plugins/FlacDecoderPlugin.cxx @@ -142,13 +142,28 @@ flac_decoder_initialize(FlacDecoder *data, FLAC__StreamDecoder *sd) static DecoderCommand FlacSubmitToClient(DecoderClient &client, FlacDecoder &d) noexcept { + if (d.tag.IsEmpty() && d.chunk.IsEmpty()) + return client.GetCommand(); + if (!d.tag.IsEmpty()) { auto cmd = client.SubmitTag(d.GetInputStream(), std::move(d.tag)); d.tag.Clear(); - return cmd; - } else - return client.GetCommand(); + if (cmd != DecoderCommand::NONE) + return cmd; + } + + if (!d.chunk.IsEmpty()) { + auto cmd = client.SubmitData(d.GetInputStream(), + d.chunk.data, + d.chunk.size, + d.kbit_rate); + d.chunk = nullptr; + if (cmd != DecoderCommand::NONE) + return cmd; + } + + return DecoderCommand::NONE; } static void