decoder/API: move functions into class DecoderBridge

This commit is contained in:
Max Kellermann 2016-11-21 21:44:57 +01:00
parent 697c3f8cb9
commit 8c342a764b
2 changed files with 63 additions and 62 deletions

View File

@ -138,6 +138,29 @@ public:
DecoderCommand SubmitTag(InputStream *is, Tag &&tag) override ;
void SubmitReplayGain(const ReplayGainInfo *replay_gain_info) override;
void SubmitMixRamp(MixRampInfo &&mix_ramp) override;
private:
/**
* Checks if we need an "initial seek". If so, then the
* initial seek is prepared, and the function returns true.
*/
bool PrepareInitialSeek();
/**
* Returns the current decoder command. May return a
* "virtual" synthesized command, e.g. to seek to the
* beginning of the CUE track.
*/
DecoderCommand GetVirtualCommand();
DecoderCommand LockGetVirtualCommand();
/**
* Sends a #Tag as-is to the #MusicPipe. Flushes the current
* chunk (DecoderBridge::chunk) if there is one.
*/
DecoderCommand DoSendTag(const Tag &tag);
bool UpdateStreamTag(InputStream *is);
};
#endif

View File

@ -83,15 +83,9 @@ DecoderBridge::Ready(const AudioFormat audio_format,
dc.client_cond.signal();
}
/**
* Checks if we need an "initial seek". If so, then the initial seek
* is prepared, and the function returns true.
*/
gcc_pure
static bool
decoder_prepare_initial_seek(DecoderBridge &bridge)
bool
DecoderBridge::PrepareInitialSeek()
{
const DecoderControl &dc = bridge.dc;
assert(dc.pipe != nullptr);
if (dc.state != DecoderState::DECODE)
@ -100,69 +94,61 @@ decoder_prepare_initial_seek(DecoderBridge &bridge)
virtual "SEEK" command */
return false;
if (bridge.initial_seek_running)
if (initial_seek_running)
/* initial seek has already begun - override any other
command */
return true;
if (bridge.initial_seek_pending) {
if (initial_seek_pending) {
if (!dc.seekable) {
/* seeking is not possible */
bridge.initial_seek_pending = false;
initial_seek_pending = false;
return false;
}
if (dc.command == DecoderCommand::NONE) {
/* begin initial seek */
bridge.initial_seek_pending = false;
bridge.initial_seek_running = true;
initial_seek_pending = false;
initial_seek_running = true;
return true;
}
/* skip initial seek when there's another command
(e.g. STOP) */
bridge.initial_seek_pending = false;
initial_seek_pending = false;
}
return false;
}
/**
* Returns the current decoder command. May return a "virtual"
* synthesized command, e.g. to seek to the beginning of the CUE
* track.
*/
gcc_pure
static DecoderCommand
decoder_get_virtual_command(DecoderBridge &bridge)
DecoderCommand
DecoderBridge::GetVirtualCommand()
{
if (bridge.error)
if (error)
/* an error has occurred: stop the decoder plugin */
return DecoderCommand::STOP;
const DecoderControl &dc = bridge.dc;
assert(dc.pipe != nullptr);
if (decoder_prepare_initial_seek(bridge))
if (PrepareInitialSeek())
return DecoderCommand::SEEK;
return dc.command;
}
gcc_pure
static DecoderCommand
decoder_lock_get_virtual_command(DecoderBridge &bridge)
DecoderCommand
DecoderBridge::LockGetVirtualCommand()
{
const ScopeLock protect(bridge.dc.mutex);
return decoder_get_virtual_command(bridge);
const ScopeLock protect(dc.mutex);
return GetVirtualCommand();
}
DecoderCommand
DecoderBridge::GetCommand()
{
return decoder_lock_get_virtual_command(*this);
return LockGetVirtualCommand();
}
void
@ -382,43 +368,35 @@ DecoderBridge::SubmitTimestamp(double t)
timestamp = t;
}
/**
* Sends a #tag as-is to the music pipe. Flushes the current chunk
* (DecoderBridge::chunk) if there is one.
*/
static DecoderCommand
do_send_tag(DecoderClient &client, const Tag &tag)
DecoderCommand
DecoderBridge::DoSendTag(const Tag &tag)
{
auto &bridge = (DecoderBridge &)client;
if (bridge.current_chunk != nullptr) {
if (current_chunk != nullptr) {
/* there is a partial chunk - flush it, we want the
tag in a new chunk */
bridge.FlushChunk();
FlushChunk();
}
assert(bridge.current_chunk == nullptr);
assert(current_chunk == nullptr);
auto *chunk = bridge.GetChunk();
auto *chunk = GetChunk();
if (chunk == nullptr) {
assert(bridge.dc.command != DecoderCommand::NONE);
return bridge.dc.command;
assert(dc.command != DecoderCommand::NONE);
return dc.command;
}
chunk->tag = new Tag(tag);
return DecoderCommand::NONE;
}
static bool
update_stream_tag(DecoderClient &client, InputStream *is)
bool
DecoderBridge::UpdateStreamTag(InputStream *is)
{
auto &bridge = (DecoderBridge &)client;
auto *tag = is != nullptr
? is->LockReadTag()
: nullptr;
if (tag == nullptr) {
tag = bridge.song_tag;
tag = song_tag;
if (tag == nullptr)
return false;
@ -426,12 +404,12 @@ update_stream_tag(DecoderClient &client, InputStream *is)
instead */
} else
/* discard the song tag; we don't need it */
delete bridge.song_tag;
delete song_tag;
bridge.song_tag = nullptr;
song_tag = nullptr;
delete bridge.stream_tag;
bridge.stream_tag = tag;
delete stream_tag;
stream_tag = tag;
return true;
}
@ -444,7 +422,7 @@ DecoderBridge::SubmitData(InputStream *is,
assert(dc.pipe != nullptr);
assert(length % dc.in_audio_format.GetFrameSize() == 0);
DecoderCommand cmd = decoder_lock_get_virtual_command(*this);
DecoderCommand cmd = LockGetVirtualCommand();
if (cmd == DecoderCommand::STOP || cmd == DecoderCommand::SEEK ||
length == 0)
@ -455,16 +433,16 @@ DecoderBridge::SubmitData(InputStream *is,
/* send stream tags */
if (update_stream_tag(*this, is)) {
if (UpdateStreamTag(is)) {
if (decoder_tag != nullptr) {
/* merge with tag from decoder plugin */
Tag *tag = Tag::Merge(*decoder_tag,
*stream_tag);
cmd = do_send_tag(*this, *tag);
cmd = DoSendTag(*tag);
delete tag;
} else
/* send only the stream tag */
cmd = do_send_tag(*this, *stream_tag);
cmd = DoSendTag(*stream_tag);
if (cmd != DecoderCommand::NONE)
return cmd;
@ -553,11 +531,11 @@ DecoderBridge::SubmitTag(InputStream *is, Tag &&tag)
/* check for a new stream tag */
update_stream_tag(*this, is);
UpdateStreamTag(is);
/* check if we're seeking */
if (decoder_prepare_initial_seek(*this))
if (PrepareInitialSeek())
/* during initial seek, no music chunk must be created
until seeking is finished; skip the rest of the
function here */
@ -570,11 +548,11 @@ DecoderBridge::SubmitTag(InputStream *is, Tag &&tag)
Tag *merged;
merged = Tag::Merge(*stream_tag, *decoder_tag);
cmd = do_send_tag(*this, *merged);
cmd = DoSendTag(*merged);
delete merged;
} else
/* send only the decoder tag */
cmd = do_send_tag(*this, *decoder_tag);
cmd = DoSendTag(*decoder_tag);
return cmd;
}