decoder/Client: add Submit methods

Replaces decoder_data() and others.
This commit is contained in:
Max Kellermann 2016-11-18 08:27:30 +01:00
parent 47a0f46ce8
commit a88040e4d5
29 changed files with 214 additions and 228 deletions

View File

@ -28,6 +28,10 @@
#include <stdint.h>
struct AudioFormat;
struct Tag;
struct ReplayGainInfo;
class MixRampInfo;
class InputStream;
/**
* An interface between the decoder plugin and the MPD core.
@ -84,6 +88,64 @@ public:
* failed.
*/
virtual void SeekError() = 0;
/**
* Sets the time stamp for the next data chunk [seconds]. The MPD
* core automatically counts it up, and a decoder plugin only needs to
* use this function if it thinks that adding to the time stamp based
* on the buffer size won't work.
*/
virtual void SubmitTimestamp(double t) = 0;
/**
* This function is called by the decoder plugin when it has
* successfully decoded block of input data.
*
* @param is an input stream which is buffering while we are waiting
* for the player
* @param data the source buffer
* @param length the number of bytes in the buffer
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
virtual DecoderCommand SubmitData(InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate) = 0;
DecoderCommand SubmitData(InputStream &is,
const void *data, size_t length,
uint16_t kbit_rate) {
return SubmitData(&is, data, length, kbit_rate);
}
/**
* This function is called by the decoder plugin when it has
* successfully decoded a tag.
*
* @param is an input stream which is buffering while we are waiting
* for the player
* @param tag the tag to send
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
virtual DecoderCommand SubmitTag(InputStream *is, Tag &&tag) = 0 ;
DecoderCommand SubmitTag(InputStream &is, Tag &&tag) {
return SubmitTag(&is, std::move(tag));
}
/**
* Set replay gain values for the following chunks.
*
* @param replay_gain_info the replay_gain_info object; may be nullptr
* to invalidate the previous replay gain values
*/
virtual void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) = 0;
/**
* Store MixRamp tags.
*/
virtual void SubmitMixRamp(MixRampInfo &&mix_ramp) = 0;
};
#endif

View File

@ -382,12 +382,11 @@ decoder_skip(DecoderClient *client, InputStream &is, size_t size)
}
void
decoder_timestamp(DecoderClient &client, double t)
Decoder::SubmitTimestamp(double t)
{
assert(t >= 0);
auto &decoder = (Decoder &)client;
decoder.timestamp = t;
timestamp = t;
}
/**
@ -446,56 +445,52 @@ update_stream_tag(DecoderClient &client, InputStream *is)
}
DecoderCommand
decoder_data(DecoderClient &client,
InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate)
Decoder::SubmitData(InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
assert(dc.state == DecoderState::DECODE);
assert(dc.pipe != nullptr);
assert(length % dc.in_audio_format.GetFrameSize() == 0);
DecoderCommand cmd = decoder_lock_get_virtual_command(decoder);
DecoderCommand cmd = decoder_lock_get_virtual_command(*this);
if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK ||
length == 0)
return cmd;
assert(!decoder.initial_seek_pending);
assert(!decoder.initial_seek_running);
assert(!initial_seek_pending);
assert(!initial_seek_running);
/* send stream tags */
if (update_stream_tag(decoder, is)) {
if (decoder.decoder_tag != nullptr) {
if (update_stream_tag(*this, is)) {
if (decoder_tag != nullptr) {
/* merge with tag from decoder plugin */
Tag *tag = Tag::Merge(*decoder.decoder_tag,
*decoder.stream_tag);
cmd = do_send_tag(decoder, *tag);
Tag *tag = Tag::Merge(*decoder_tag,
*stream_tag);
cmd = do_send_tag(*this, *tag);
delete tag;
} else
/* send only the stream tag */
cmd = do_send_tag(decoder, *decoder.stream_tag);
cmd = do_send_tag(*this, *stream_tag);
if (cmd != DecoderCommand::NONE)
return cmd;
}
if (decoder.convert != nullptr) {
if (convert != nullptr) {
assert(dc.in_audio_format != dc.out_audio_format);
try {
auto result = decoder.convert->Convert({data, length});
auto result = convert->Convert({data, length});
data = result.data;
length = result.size;
} catch (const std::runtime_error &e) {
/* the PCM conversion has failed - stop
playback, since we have no better way to
bail out */
decoder.error = std::current_exception();
error = std::current_exception();
return DecoderCommand::STOP;
}
} else {
@ -503,10 +498,9 @@ decoder_data(DecoderClient &client,
}
while (length > 0) {
MusicChunk *chunk;
bool full;
chunk = decoder.GetChunk();
auto *chunk = GetChunk();
if (chunk == nullptr) {
assert(dc.command != DecoderCommand::NONE);
return dc.command;
@ -514,12 +508,12 @@ decoder_data(DecoderClient &client,
const auto dest =
chunk->Write(dc.out_audio_format,
SongTime::FromS(decoder.timestamp) -
SongTime::FromS(timestamp) -
dc.song->GetStartTime(),
kbit_rate);
if (dest.IsEmpty()) {
/* the chunk is full, flush it */
decoder.FlushChunk();
FlushChunk();
continue;
}
@ -534,17 +528,17 @@ decoder_data(DecoderClient &client,
full = chunk->Expand(dc.out_audio_format, nbytes);
if (full) {
/* the chunk is full, flush it */
decoder.FlushChunk();
FlushChunk();
}
data = (const uint8_t *)data + nbytes;
length -= nbytes;
decoder.timestamp += (double)nbytes /
timestamp += (double)nbytes /
dc.out_audio_format.GetTimeToSize();
if (dc.end_time.IsPositive() &&
decoder.timestamp >= dc.end_time.ToDoubleS())
timestamp >= dc.end_time.ToDoubleS())
/* the end of this range has been reached:
stop decoding */
return DecoderCommand::STOP;
@ -554,11 +548,8 @@ decoder_data(DecoderClient &client,
}
DecoderCommand
decoder_tag(DecoderClient &client, InputStream *is,
Tag &&tag)
Decoder::SubmitTag(InputStream *is, Tag &&tag)
{
auto &decoder = (Decoder &)client;
gcc_unused const DecoderControl &dc = decoder.dc;
DecoderCommand cmd;
assert(dc.state == DecoderState::DECODE);
@ -566,16 +557,16 @@ decoder_tag(DecoderClient &client, InputStream *is,
/* save the tag */
delete decoder.decoder_tag;
decoder.decoder_tag = new Tag(std::move(tag));
delete decoder_tag;
decoder_tag = new Tag(std::move(tag));
/* check for a new stream tag */
update_stream_tag(decoder, is);
update_stream_tag(*this, is);
/* check if we're seeking */
if (decoder_prepare_initial_seek(decoder))
if (decoder_prepare_initial_seek(*this))
/* during initial seek, no music chunk must be created
until seeking is finished; skip the rest of the
function here */
@ -583,28 +574,24 @@ decoder_tag(DecoderClient &client, InputStream *is,
/* send tag to music pipe */
if (decoder.stream_tag != nullptr) {
if (stream_tag != nullptr) {
/* merge with tag from input stream */
Tag *merged;
merged = Tag::Merge(*decoder.stream_tag,
*decoder.decoder_tag);
cmd = do_send_tag(decoder, *merged);
merged = Tag::Merge(*stream_tag, *decoder_tag);
cmd = do_send_tag(*this, *merged);
delete merged;
} else
/* send only the decoder tag */
cmd = do_send_tag(decoder, *decoder.decoder_tag);
cmd = do_send_tag(*this, *decoder_tag);
return cmd;
}
void
decoder_replay_gain(DecoderClient &client,
const ReplayGainInfo *replay_gain_info)
Decoder::SubmitReplayGain(const ReplayGainInfo *new_replay_gain_info)
{
auto &decoder = (Decoder &)client;
if (replay_gain_info != nullptr) {
if (new_replay_gain_info != nullptr) {
static unsigned serial;
if (++serial == 0)
serial = 1;
@ -614,32 +601,29 @@ decoder_replay_gain(DecoderClient &client,
if (rgm != REPLAY_GAIN_ALBUM)
rgm = REPLAY_GAIN_TRACK;
const auto &tuple = replay_gain_info->tuples[rgm];
const auto &tuple = new_replay_gain_info->tuples[rgm];
const auto scale =
tuple.CalculateScale(replay_gain_preamp,
replay_gain_missing_preamp,
replay_gain_limit);
decoder.dc.replay_gain_db = 20.0 * log10f(scale);
dc.replay_gain_db = 20.0 * log10f(scale);
}
decoder.replay_gain_info = *replay_gain_info;
decoder.replay_gain_serial = serial;
replay_gain_info = *new_replay_gain_info;
replay_gain_serial = serial;
if (decoder.current_chunk != nullptr) {
if (current_chunk != nullptr) {
/* flush the current chunk because the new
replay gain values affect the following
samples */
decoder.FlushChunk();
FlushChunk();
}
} else
decoder.replay_gain_serial = 0;
replay_gain_serial = 0;
}
void
decoder_mixramp(DecoderClient &client, MixRampInfo &&mix_ramp)
Decoder::SubmitMixRamp(MixRampInfo &&mix_ramp)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
dc.SetMixRamp(std::move(mix_ramp));
}

View File

@ -104,73 +104,4 @@ decoder_read_full(DecoderClient *decoder, InputStream &is,
bool
decoder_skip(DecoderClient *decoder, InputStream &is, size_t size);
/**
* Sets the time stamp for the next data chunk [seconds]. The MPD
* core automatically counts it up, and a decoder plugin only needs to
* use this function if it thinks that adding to the time stamp based
* on the buffer size won't work.
*/
void
decoder_timestamp(DecoderClient &decoder, double t);
/**
* This function is called by the decoder plugin when it has
* successfully decoded block of input data.
*
* @param decoder the decoder object
* @param is an input stream which is buffering while we are waiting
* for the player
* @param data the source buffer
* @param length the number of bytes in the buffer
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
DecoderCommand
decoder_data(DecoderClient &decoder, InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate);
static inline DecoderCommand
decoder_data(DecoderClient &decoder, InputStream &is,
const void *data, size_t length,
uint16_t kbit_rate)
{
return decoder_data(decoder, &is, data, length, kbit_rate);
}
/**
* This function is called by the decoder plugin when it has
* successfully decoded a tag.
*
* @param is an input stream which is buffering while we are waiting
* for the player
* @param tag the tag to send
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
DecoderCommand
decoder_tag(DecoderClient &decoder, InputStream *is, Tag &&tag);
static inline DecoderCommand
decoder_tag(DecoderClient &decoder, InputStream &is, Tag &&tag)
{
return decoder_tag(decoder, &is, std::move(tag));
}
/**
* Set replay gain values for the following chunks.
*
* @param replay_gain_info the replay_gain_info object; may be nullptr
* to invalidate the previous replay gain values
*/
void
decoder_replay_gain(DecoderClient &decoder,
const ReplayGainInfo *replay_gain_info);
/**
* Store MixRamp tags.
*/
void
decoder_mixramp(DecoderClient &decoder, MixRampInfo &&mix_ramp);
#endif

View File

@ -124,6 +124,13 @@ struct Decoder final : DecoderClient {
SongTime GetSeekTime() override;
uint64_t GetSeekFrame() override;
void SeekError() override;
void SubmitTimestamp(double t) override;
DecoderCommand SubmitData(InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate) override;
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) override ;
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) override;
void SubmitMixRamp(MixRampInfo &&mix_ramp) override;
};
#endif

View File

@ -245,14 +245,14 @@ decoder_run_stream_fallback(Decoder &decoder, InputStream &is)
/**
* Attempt to load replay gain data, and pass it to
* decoder_replay_gain().
* DecoderClient::SubmitReplayGain().
*/
static void
LoadReplayGain(Decoder &decoder, InputStream &is)
LoadReplayGain(DecoderClient &client, InputStream &is)
{
ReplayGainInfo info;
if (replay_gain_ape_read(is, info))
decoder_replay_gain(decoder, &info);
client.SubmitReplayGain(&info);
}
/**

View File

@ -73,9 +73,9 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
int16_t buffer[2048];
constexpr unsigned frames_per_buffer = ARRAY_SIZE(buffer) / 2;
opl.update(buffer, frames_per_buffer);
cmd = decoder_data(client, nullptr,
buffer, sizeof(buffer),
0);
cmd = client.SubmitData(nullptr,
buffer, sizeof(buffer),
0);
} while (cmd == DecoderCommand::NONE);
delete player;

View File

@ -223,9 +223,9 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
if (nframes <= 0)
break;
cmd = decoder_data(client, nullptr,
chunk, nframes * frame_size,
kbit_rate);
cmd = client.SubmitData(nullptr,
chunk, nframes * frame_size,
kbit_rate);
if (cmd == DecoderCommand::SEEK) {
AFframecount frame = client.GetSeekFrame();

View File

@ -408,8 +408,8 @@ dsdiff_decode_chunk(DecoderClient &client, InputStream &is,
if (lsbitfirst)
bit_reverse_buffer(buffer, buffer + nbytes);
cmd = decoder_data(client, is, buffer, nbytes,
sample_rate / 1000);
cmd = client.SubmitData(is, buffer, nbytes,
sample_rate / 1000);
}
return true;

View File

@ -289,9 +289,9 @@ dsf_decode_chunk(DecoderClient &client, InputStream &is,
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
cmd = decoder_data(client, is,
interleaved_buffer, block_size,
sample_rate / 1000);
cmd = client.SubmitData(is,
interleaved_buffer, block_size,
sample_rate / 1000);
++i;
}

View File

@ -393,9 +393,9 @@ faad_stream_decode(DecoderClient &client, InputStream &is,
/* send PCM samples to MPD */
cmd = decoder_data(client, is, decoded,
(size_t)frame_info.samples * 2,
bit_rate);
cmd = client.SubmitData(is, decoded,
(size_t)frame_info.samples * 2,
bit_rate);
} while (cmd != DecoderCommand::STOP);
}

View File

@ -218,7 +218,8 @@ PtsToPcmFrame(uint64_t pts, const AVStream &stream,
}
/**
* Invoke decoder_data() with the contents of an #AVFrame.
* Invoke DecoderClient::SubmitData() with the contents of an
* #AVFrame.
*/
static DecoderCommand
FfmpegSendFrame(DecoderClient &client, InputStream &is,
@ -250,9 +251,9 @@ FfmpegSendFrame(DecoderClient &client, InputStream &is,
skip_bytes = 0;
}
return decoder_data(client, is,
output_buffer.data, output_buffer.size,
codec_context.bit_rate / 1000);
return client.SubmitData(is,
output_buffer.data, output_buffer.size,
codec_context.bit_rate / 1000);
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0)
@ -330,9 +331,8 @@ ffmpeg_send_packet(DecoderClient &client, InputStream &is,
if (cur_frame < min_frame)
skip_bytes = pcm_frame_size * (min_frame - cur_frame);
} else
decoder_timestamp(client,
FfmpegTimeToDouble(pts,
stream.time_base));
client.SubmitTimestamp(FfmpegTimeToDouble(pts,
stream.time_base));
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0)
@ -540,10 +540,10 @@ FfmpegParseMetaData(DecoderClient &client,
FfmpegParseMetaData(format_context, audio_stream, rg, mr);
if (rg.IsDefined())
decoder_replay_gain(client, &rg);
client.SubmitReplayGain(&rg);
if (mr.IsDefined())
decoder_mixramp(client, std::move(mr));
client.SubmitMixRamp(std::move(mr));
}
static void
@ -576,7 +576,7 @@ FfmpegScanTag(const AVFormatContext &format_context, int audio_stream,
/**
* Check if a new stream tag was received and pass it to
* decoder_tag().
* DecoderClient::SubmitTag().
*/
static void
FfmpegCheckTag(DecoderClient &client, InputStream &is,
@ -593,7 +593,7 @@ FfmpegCheckTag(DecoderClient &client, InputStream &is,
TagBuilder tag;
FfmpegScanTag(format_context, audio_stream, tag);
if (!tag.IsEmpty())
decoder_tag(client, is, tag.Commit());
client.SubmitTag(is, tag.Commit());
}
#endif

View File

@ -77,9 +77,9 @@ FlacDecoder::OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc)
{
ReplayGainInfo rgi;
if (flac_parse_replay_gain(rgi, vc))
decoder_replay_gain(*GetClient(), &rgi);
GetClient()->SubmitReplayGain(&rgi);
decoder_mixramp(*GetClient(), flac_parse_mixramp(vc));
GetClient()->SubmitMixRamp(flac_parse_mixramp(vc));
tag = flac_vorbis_comments_to_tag(&vc);
}
@ -148,9 +148,9 @@ FlacDecoder::OnWrite(const FLAC__Frame &frame,
unsigned bit_rate = nbytes * 8 * frame.header.sample_rate /
(1000 * frame.header.blocksize);
auto cmd = decoder_data(*GetClient(), GetInputStream(),
data.data, data.size,
bit_rate);
auto cmd = GetClient()->SubmitData(GetInputStream(),
data.data, data.size,
bit_rate);
switch (cmd) {
case DecoderCommand::NONE:
case DecoderCommand::START:

View File

@ -147,8 +147,8 @@ flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec)
while (true) {
DecoderCommand cmd;
if (!data->tag.IsEmpty()) {
cmd = decoder_tag(client, data->GetInputStream(),
std::move(data->tag));
cmd = client.SubmitTag(data->GetInputStream(),
std::move(data->tag));
data->tag.Clear();
} else
cmd = client.GetCommand();

View File

@ -176,8 +176,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
if (ret != 0)
break;
cmd = decoder_data(client, nullptr, buffer, sizeof(buffer),
0);
cmd = client.SubmitData(nullptr, buffer, sizeof(buffer), 0);
if (cmd != DecoderCommand::NONE)
break;
}

View File

@ -190,7 +190,7 @@ gme_file_decode(DecoderClient &client, Path path_fs)
return;
}
cmd = decoder_data(client, nullptr, buf, sizeof(buf), 0);
cmd = client.SubmitData(nullptr, buf, sizeof(buf), 0);
if (cmd == DecoderCommand::SEEK) {
unsigned where = client.GetSeekTime().ToMS();
gme_err = gme_seek(emu, where);

View File

@ -182,13 +182,14 @@ struct MadDecoder {
void UpdateTimerNextFrame();
/**
* Sends the synthesized current frame via decoder_data().
* Sends the synthesized current frame via
* DecoderClient::SubmitData().
*/
DecoderCommand SendPCM(unsigned i, unsigned pcm_length);
/**
* Synthesize the current frame and send it via
* decoder_data().
* DecoderClient::SubmitData().
*/
DecoderCommand SyncAndSend();
@ -361,11 +362,11 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
ReplayGainInfo rgi;
if (parse_id3_replay_gain_info(rgi, id3_tag)) {
decoder_replay_gain(*client, &rgi);
client->SubmitReplayGain(&rgi);
found_replay_gain = true;
}
decoder_mixramp(*client, parse_id3_mixramp(id3_tag));
client->SubmitMixRamp(parse_id3_mixramp(id3_tag));
}
id3_tag_delete(id3_tag);
@ -806,7 +807,7 @@ MadDecoder::DecodeFirstFrame(Tag **tag)
rgi.Clear();
rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
decoder_replay_gain(*client, &rgi);
client->SubmitReplayGain(&rgi);
}
}
}
@ -903,9 +904,9 @@ MadDecoder::SendPCM(unsigned i, unsigned pcm_length)
MAD_NCHANNELS(&frame.header));
num_samples *= MAD_NCHANNELS(&frame.header);
auto cmd = decoder_data(*client, input_stream, output_buffer,
sizeof(output_buffer[0]) * num_samples,
bit_rate / 1000);
auto cmd = client->SubmitData(input_stream, output_buffer,
sizeof(output_buffer[0]) * num_samples,
bit_rate / 1000);
if (cmd != DecoderCommand::NONE)
return cmd;
}
@ -1010,8 +1011,8 @@ MadDecoder::Read()
ret = DecodeNextFrameHeader(&tag);
if (tag != nullptr) {
decoder_tag(*client, input_stream,
std::move(*tag));
client->SubmitTag(input_stream,
std::move(*tag));
delete tag;
}
} while (ret == DECODE_CONT);
@ -1057,7 +1058,7 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
data.total_time);
if (tag != nullptr) {
decoder_tag(client, input_stream, std::move(*tag));
client.SubmitTag(input_stream, std::move(*tag));
delete tag;
}

View File

@ -177,7 +177,7 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
DecoderCommand cmd = DecoderCommand::NONE;
while (cmd == DecoderCommand::NONE && Player_Active()) {
ret = VC_WriteBytes(buffer, sizeof(buffer));
cmd = decoder_data(client, nullptr, buffer, ret, 0);
cmd = client.SubmitData(nullptr, buffer, ret, 0);
}
Player_Stop();

View File

@ -160,9 +160,9 @@ mod_decode(DecoderClient &client, InputStream &is)
if (ret <= 0)
break;
cmd = decoder_data(client, nullptr,
audio_buffer, ret,
0);
cmd = client.SubmitData(nullptr,
audio_buffer, ret,
0);
if (cmd == DecoderCommand::SEEK) {
ModPlug_Seek(f, client.GetSeekTime().ToMS());

View File

@ -172,7 +172,7 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
rgi.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.);
rgi.tuples[REPLAY_GAIN_TRACK].peak = pow(10, info.peak_title / 256. / 20) / 32767;
decoder_replay_gain(client, &rgi);
client.SubmitReplayGain(&rgi);
client.Ready(audio_format, is.IsSeekable(),
SongTime::FromS(mpc_streaminfo_get_length(&info)));
@ -213,9 +213,9 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
long bit_rate = unsigned(frame.bits) * audio_format.sample_rate
/ (1000 * frame.samples);
cmd = decoder_data(client, is,
chunk, ret * sizeof(chunk[0]),
bit_rate);
cmd = client.SubmitData(is,
chunk, ret * sizeof(chunk[0]),
bit_rate);
} while (cmd != DecoderCommand::STOP);
mpc_demux_exit(demux);

View File

@ -129,7 +129,7 @@ mpd_mpg123_id3v2_tag(DecoderClient &client, const mpg123_id3v2 &id3v2)
for (size_t i = 0, n = id3v2.comments; i < n; ++i)
AddTagItem(tag, TAG_COMMENT, id3v2.comment_list[i].text);
decoder_tag(client, nullptr, tag.Commit());
client.SubmitTag(nullptr, tag.Commit());
}
static void
@ -154,10 +154,10 @@ mpd_mpg123_id3v2_extras(DecoderClient &client, const mpg123_id3v2 &id3v2)
}
if (found_replay_gain)
decoder_replay_gain(client, &replay_gain);
client.SubmitReplayGain(&replay_gain);
if (found_mixramp)
decoder_mixramp(client, std::move(mix_ramp));
client.SubmitMixRamp(std::move(mix_ramp));
}
static void
@ -257,7 +257,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
/* send to MPD */
cmd = decoder_data(client, nullptr, buffer, nbytes, info.bitrate);
cmd = client.SubmitData(nullptr, buffer, nbytes, info.bitrate);
if (cmd == DecoderCommand::SEEK) {
off_t c = client.GetSeekFrame();
@ -266,7 +266,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
client.SeekError();
else {
client.CommandFinished();
decoder_timestamp(client, c/(double)audio_format.sample_rate);
client.SubmitTimestamp(c / (double)audio_format.sample_rate);
}
cmd = DecoderCommand::NONE;

View File

@ -212,10 +212,10 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
&rgi,
add_tag_handler, &tag_builder) &&
!tag_builder.IsEmpty()) {
decoder_replay_gain(client, &rgi);
client.SubmitReplayGain(&rgi);
Tag tag = tag_builder.Commit();
auto cmd = decoder_tag(client, input_stream, std::move(tag));
auto cmd = client.SubmitTag(input_stream, std::move(tag));
if (cmd != DecoderCommand::NONE)
throw cmd;
}
@ -237,16 +237,15 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet)
if (nframes > 0) {
const size_t nbytes = nframes * frame_size;
auto cmd = decoder_data(client, input_stream,
output_buffer, nbytes,
0);
auto cmd = client.SubmitData(input_stream,
output_buffer, nbytes,
0);
if (cmd != DecoderCommand::NONE)
throw cmd;
if (packet.granulepos > 0)
decoder_timestamp(client,
double(packet.granulepos)
/ opus_sample_rate);
client.SubmitTimestamp(double(packet.granulepos)
/ opus_sample_rate);
}
}

View File

@ -154,7 +154,8 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
auto r = buffer.Read();
/* round down to the nearest frame size, because we
must not pass partial frames to decoder_data() */
must not pass partial frames to
DecoderClient::SubmitData() */
r.size -= r.size % frame_size;
buffer.Consume(r.size);
@ -165,7 +166,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
(uint16_t *)(r.data + r.size));
cmd = !r.IsEmpty()
? decoder_data(client, is, r.data, r.size, 0)
? client.SubmitData(is, r.data, r.size, 0)
: client.GetCommand();
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = client.GetSeekFrame();

View File

@ -366,9 +366,9 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
const size_t nbytes = result;
#endif
decoder_timestamp(client, (double)player.time() / timebase);
client.SubmitTimestamp((double)player.time() / timebase);
cmd = decoder_data(client, nullptr, buffer, nbytes, 0);
cmd = client.SubmitData(nullptr, buffer, nbytes, 0);
if (cmd == DecoderCommand::SEEK) {
unsigned data_time = player.time();

View File

@ -221,9 +221,9 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
if (num_frames <= 0)
break;
cmd = decoder_data(client, is,
buffer, num_frames * frame_size,
0);
cmd = client.SubmitData(is,
buffer, num_frames * frame_size,
0);
if (cmd == DecoderCommand::SEEK) {
sf_count_t c = client.GetSeekFrame();
c = sf_seek(sf, c, SEEK_SET);

View File

@ -156,7 +156,7 @@ vorbis_send_comments(DecoderClient &client, InputStream &is,
if (!tag)
return;
decoder_tag(client, is, std::move(*tag));
client.SubmitTag(is, std::move(*tag));
delete tag;
}
@ -211,9 +211,9 @@ VorbisDecoder::SubmitSomePcm()
vorbis_synthesis_read(&dsp, n_frames);
const size_t nbytes = n_frames * frame_size;
auto cmd = decoder_data(client, input_stream,
buffer, nbytes,
0);
auto cmd = client.SubmitData(input_stream,
buffer, nbytes,
0);
if (cmd != DecoderCommand::NONE)
throw cmd;
@ -252,7 +252,7 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
ReplayGainInfo rgi;
if (vorbis_comments_to_replay_gain(rgi, vc.user_comments))
decoder_replay_gain(client, &rgi);
client.SubmitReplayGain(&rgi);
} else {
if (!dsp_initialized) {
dsp_initialized = true;
@ -277,8 +277,7 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
#ifndef HAVE_TREMOR
if (packet.granulepos > 0)
decoder_timestamp(client,
vorbis_granule_time(&dsp, packet.granulepos));
client.SubmitTimestamp(vorbis_granule_time(&dsp, packet.granulepos));
#endif
}
}

View File

@ -196,9 +196,9 @@ wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
format_samples(bytes_per_sample, chunk,
samples_got * audio_format.channels);
cmd = decoder_data(client, nullptr, chunk,
samples_got * output_sample_size,
bitrate);
cmd = client.SubmitData(nullptr, chunk,
samples_got * output_sample_size,
bitrate);
}
}
@ -563,7 +563,7 @@ wavpack_filedecode(DecoderClient &client, Path path_fs)
ReplayGainInfo rgi;
if (wavpack_replaygain(rgi, wpc))
decoder_replay_gain(client, &rgi);
client.SubmitReplayGain(&rgi);
wavpack_decode(client, wpc, true);

View File

@ -75,7 +75,7 @@ wildmidi_output(DecoderClient &client, midi *wm)
if (length <= 0)
return DecoderCommand::STOP;
return decoder_data(client, nullptr, buffer, length, 0);
return client.SubmitData(nullptr, buffer, length, 0);
}
static void

View File

@ -127,16 +127,14 @@ decoder_skip(DecoderClient *client, InputStream &is, size_t size)
}
void
decoder_timestamp(gcc_unused DecoderClient &client,
gcc_unused double t)
FakeDecoder::SubmitTimestamp(gcc_unused double t)
{
}
DecoderCommand
decoder_data(gcc_unused DecoderClient &client,
gcc_unused InputStream *is,
const void *data, size_t datalen,
gcc_unused uint16_t kbit_rate)
FakeDecoder::SubmitData(gcc_unused InputStream *is,
const void *data, size_t datalen,
gcc_unused uint16_t kbit_rate)
{
static uint16_t prev_kbit_rate;
if (kbit_rate != prev_kbit_rate) {
@ -149,9 +147,8 @@ decoder_data(gcc_unused DecoderClient &client,
}
DecoderCommand
decoder_tag(gcc_unused DecoderClient &client,
gcc_unused InputStream *is,
Tag &&tag)
FakeDecoder::SubmitTag(gcc_unused InputStream *is,
Tag &&tag)
{
fprintf(stderr, "TAG: duration=%f\n", tag.duration.ToDoubleS());
@ -162,8 +159,7 @@ decoder_tag(gcc_unused DecoderClient &client,
}
void
decoder_replay_gain(gcc_unused DecoderClient &client,
const ReplayGainInfo *rgi)
FakeDecoder::SubmitReplayGain(const ReplayGainInfo *rgi)
{
const ReplayGainTuple *tuple = &rgi->tuples[REPLAY_GAIN_ALBUM];
if (tuple->IsDefined())
@ -177,7 +173,7 @@ decoder_replay_gain(gcc_unused DecoderClient &client,
}
void
decoder_mixramp(gcc_unused DecoderClient &client, gcc_unused MixRampInfo &&mix_ramp)
FakeDecoder::SubmitMixRamp(gcc_unused MixRampInfo &&mix_ramp)
{
fprintf(stderr, "MixRamp: start='%s' end='%s'\n",
mix_ramp.GetStart(), mix_ramp.GetEnd());

View File

@ -39,6 +39,13 @@ struct FakeDecoder final : DecoderClient {
SongTime GetSeekTime() override;
uint64_t GetSeekFrame() override;
void SeekError() override;
void SubmitTimestamp(double t) override;
DecoderCommand SubmitData(InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate) override;
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) override ;
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) override;
void SubmitMixRamp(MixRampInfo &&mix_ramp) override;
};
#endif