MusicPipe: add MusicBuffer reference
This tiny amount of overhead allows omitting the MusicBuffer in Clear().
This commit is contained in:
parent
cb412b221c
commit
9f14e7a98d
@ -73,7 +73,7 @@ MusicPipe::Shift() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MusicPipe::Clear(MusicBuffer &buffer) noexcept
|
MusicPipe::Clear() noexcept
|
||||||
{
|
{
|
||||||
MusicChunk *chunk;
|
MusicChunk *chunk;
|
||||||
|
|
||||||
|
@ -37,6 +37,11 @@ class MusicBuffer;
|
|||||||
* tail, and the other consumes them from the head.
|
* tail, and the other consumes them from the head.
|
||||||
*/
|
*/
|
||||||
class MusicPipe {
|
class MusicPipe {
|
||||||
|
/**
|
||||||
|
* The #MusicBuffer where all chunks must be returned.
|
||||||
|
*/
|
||||||
|
MusicBuffer &buffer;
|
||||||
|
|
||||||
/** the first chunk */
|
/** the first chunk */
|
||||||
MusicChunk *head = nullptr;
|
MusicChunk *head = nullptr;
|
||||||
|
|
||||||
@ -57,7 +62,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Creates a new #MusicPipe object. It is empty.
|
* Creates a new #MusicPipe object. It is empty.
|
||||||
*/
|
*/
|
||||||
MusicPipe() = default;
|
explicit MusicPipe(MusicBuffer &_buffer) noexcept
|
||||||
|
:buffer(_buffer) {}
|
||||||
|
|
||||||
MusicPipe(const MusicPipe &) = delete;
|
MusicPipe(const MusicPipe &) = delete;
|
||||||
|
|
||||||
@ -71,6 +77,10 @@ public:
|
|||||||
|
|
||||||
MusicPipe &operator=(const MusicPipe &) = delete;
|
MusicPipe &operator=(const MusicPipe &) = delete;
|
||||||
|
|
||||||
|
MusicBuffer &GetBuffer() noexcept {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/**
|
/**
|
||||||
* Checks if the audio format if the chunk is equal to the specified
|
* Checks if the audio format if the chunk is equal to the specified
|
||||||
@ -106,10 +116,8 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the whole pipe and returns the chunks to the buffer.
|
* Clears the whole pipe and returns the chunks to the buffer.
|
||||||
*
|
|
||||||
* @param buffer the buffer object to return the chunks to
|
|
||||||
*/
|
*/
|
||||||
void Clear(MusicBuffer &buffer) noexcept;
|
void Clear() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes a chunk to the tail of the pipe.
|
* Pushes a chunk to the tail of the pipe.
|
||||||
|
@ -98,7 +98,7 @@ DecoderBridge::GetChunk() noexcept
|
|||||||
return current_chunk;
|
return current_chunk;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
current_chunk = dc.buffer->Allocate();
|
current_chunk = dc.pipe->GetBuffer().Allocate();
|
||||||
if (current_chunk != nullptr) {
|
if (current_chunk != nullptr) {
|
||||||
current_chunk->replay_gain_serial = replay_gain_serial;
|
current_chunk->replay_gain_serial = replay_gain_serial;
|
||||||
if (replay_gain_serial != 0)
|
if (replay_gain_serial != 0)
|
||||||
@ -123,7 +123,7 @@ DecoderBridge::FlushChunk()
|
|||||||
|
|
||||||
auto *chunk = std::exchange(current_chunk, nullptr);
|
auto *chunk = std::exchange(current_chunk, nullptr);
|
||||||
if (chunk->IsEmpty())
|
if (chunk->IsEmpty())
|
||||||
dc.buffer->Return(chunk);
|
dc.pipe->GetBuffer().Return(chunk);
|
||||||
else
|
else
|
||||||
dc.pipe->Push(chunk);
|
dc.pipe->Push(chunk);
|
||||||
|
|
||||||
@ -303,11 +303,11 @@ DecoderBridge::CommandFinished()
|
|||||||
/* delete frames from the old song position */
|
/* delete frames from the old song position */
|
||||||
|
|
||||||
if (current_chunk != nullptr) {
|
if (current_chunk != nullptr) {
|
||||||
dc.buffer->Return(current_chunk);
|
dc.pipe->GetBuffer().Return(current_chunk);
|
||||||
current_chunk = nullptr;
|
current_chunk = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.pipe->Clear(*dc.buffer);
|
dc.pipe->Clear();
|
||||||
|
|
||||||
if (convert != nullptr)
|
if (convert != nullptr)
|
||||||
convert->Reset();
|
convert->Reset();
|
||||||
|
@ -92,7 +92,7 @@ DecoderControl::IsCurrentSong(const DetachedSong &_song) const noexcept
|
|||||||
void
|
void
|
||||||
DecoderControl::Start(std::unique_ptr<DetachedSong> _song,
|
DecoderControl::Start(std::unique_ptr<DetachedSong> _song,
|
||||||
SongTime _start_time, SongTime _end_time,
|
SongTime _start_time, SongTime _end_time,
|
||||||
MusicBuffer &_buffer, MusicPipe &_pipe) noexcept
|
MusicPipe &_pipe) noexcept
|
||||||
{
|
{
|
||||||
assert(_song != nullptr);
|
assert(_song != nullptr);
|
||||||
assert(_pipe.IsEmpty());
|
assert(_pipe.IsEmpty());
|
||||||
@ -100,7 +100,6 @@ DecoderControl::Start(std::unique_ptr<DetachedSong> _song,
|
|||||||
song = std::move(_song);
|
song = std::move(_song);
|
||||||
start_time = _start_time;
|
start_time = _start_time;
|
||||||
end_time = _end_time;
|
end_time = _end_time;
|
||||||
buffer = &_buffer;
|
|
||||||
pipe = &_pipe;
|
pipe = &_pipe;
|
||||||
|
|
||||||
ClearError();
|
ClearError();
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
class DetachedSong;
|
class DetachedSong;
|
||||||
class MusicBuffer;
|
|
||||||
class MusicPipe;
|
class MusicPipe;
|
||||||
|
|
||||||
enum class DecoderState : uint8_t {
|
enum class DecoderState : uint8_t {
|
||||||
@ -152,9 +151,6 @@ struct DecoderControl final : InputStreamHandler {
|
|||||||
|
|
||||||
SignedSongTime total_time;
|
SignedSongTime total_time;
|
||||||
|
|
||||||
/** the #MusicChunk allocator */
|
|
||||||
MusicBuffer *buffer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The destination pipe for decoded chunks. The caller thread
|
* The destination pipe for decoded chunks. The caller thread
|
||||||
* owns this object, and is responsible for freeing it.
|
* owns this object, and is responsible for freeing it.
|
||||||
@ -383,7 +379,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Start(std::unique_ptr<DetachedSong> song,
|
void Start(std::unique_ptr<DetachedSong> song,
|
||||||
SongTime start_time, SongTime end_time,
|
SongTime start_time, SongTime end_time,
|
||||||
MusicBuffer &buffer, MusicPipe &pipe) noexcept;
|
MusicPipe &pipe) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock the object.
|
* Caller must lock the object.
|
||||||
|
@ -551,7 +551,7 @@ DecoderControl::RunThread() noexcept
|
|||||||
/* we need to clear the pipe here; usually the
|
/* we need to clear the pipe here; usually the
|
||||||
PlayerThread is responsible, but it is not
|
PlayerThread is responsible, but it is not
|
||||||
aware that the decoder has finished */
|
aware that the decoder has finished */
|
||||||
pipe->Clear(*buffer);
|
pipe->Clear();
|
||||||
|
|
||||||
decoder_run(*this);
|
decoder_run(*this);
|
||||||
break;
|
break;
|
||||||
|
@ -207,7 +207,6 @@ MultipleOutputs::SetReplayGainMode(ReplayGainMode mode) noexcept
|
|||||||
void
|
void
|
||||||
MultipleOutputs::Play(MusicChunk *chunk)
|
MultipleOutputs::Play(MusicChunk *chunk)
|
||||||
{
|
{
|
||||||
assert(buffer != nullptr);
|
|
||||||
assert(pipe != nullptr);
|
assert(pipe != nullptr);
|
||||||
assert(chunk != nullptr);
|
assert(chunk != nullptr);
|
||||||
assert(chunk->CheckFormat(input_audio_format));
|
assert(chunk->CheckFormat(input_audio_format));
|
||||||
@ -224,21 +223,18 @@ MultipleOutputs::Play(MusicChunk *chunk)
|
|||||||
|
|
||||||
void
|
void
|
||||||
MultipleOutputs::Open(const AudioFormat audio_format,
|
MultipleOutputs::Open(const AudioFormat audio_format,
|
||||||
MusicBuffer &_buffer)
|
MusicBuffer &buffer)
|
||||||
{
|
{
|
||||||
bool ret = false, enabled = false;
|
bool ret = false, enabled = false;
|
||||||
|
|
||||||
assert(buffer == nullptr || buffer == &_buffer);
|
assert(pipe == nullptr || &pipe->GetBuffer() == &buffer);
|
||||||
assert((pipe == nullptr) == (buffer == nullptr));
|
|
||||||
|
|
||||||
buffer = &_buffer;
|
|
||||||
|
|
||||||
/* the audio format must be the same as existing chunks in the
|
/* the audio format must be the same as existing chunks in the
|
||||||
pipe */
|
pipe */
|
||||||
assert(pipe == nullptr || pipe->CheckFormat(audio_format));
|
assert(pipe == nullptr || pipe->CheckFormat(audio_format));
|
||||||
|
|
||||||
if (pipe == nullptr)
|
if (pipe == nullptr)
|
||||||
pipe = new MusicPipe();
|
pipe = new MusicPipe(buffer);
|
||||||
else
|
else
|
||||||
/* if the pipe hasn't been cleared, the the audio
|
/* if the pipe hasn't been cleared, the the audio
|
||||||
format must not have changed */
|
format must not have changed */
|
||||||
@ -321,7 +317,6 @@ MultipleOutputs::CheckPipe() noexcept
|
|||||||
MusicChunk *shifted;
|
MusicChunk *shifted;
|
||||||
bool locked[outputs.size()];
|
bool locked[outputs.size()];
|
||||||
|
|
||||||
assert(buffer != nullptr);
|
|
||||||
assert(pipe != nullptr);
|
assert(pipe != nullptr);
|
||||||
|
|
||||||
while ((chunk = pipe->Peek()) != nullptr) {
|
while ((chunk = pipe->Peek()) != nullptr) {
|
||||||
@ -355,7 +350,7 @@ MultipleOutputs::CheckPipe() noexcept
|
|||||||
outputs[i]->mutex.unlock();
|
outputs[i]->mutex.unlock();
|
||||||
|
|
||||||
/* return the chunk to the buffer */
|
/* return the chunk to the buffer */
|
||||||
buffer->Return(shifted);
|
pipe->GetBuffer().Return(shifted);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -394,7 +389,7 @@ MultipleOutputs::Cancel() noexcept
|
|||||||
/* clear the music pipe and return all chunks to the buffer */
|
/* clear the music pipe and return all chunks to the buffer */
|
||||||
|
|
||||||
if (pipe != nullptr)
|
if (pipe != nullptr)
|
||||||
pipe->Clear(*buffer);
|
pipe->Clear();
|
||||||
|
|
||||||
/* the audio outputs are now waiting for a signal, to
|
/* the audio outputs are now waiting for a signal, to
|
||||||
synchronize the cleared music pipe */
|
synchronize the cleared music pipe */
|
||||||
@ -413,15 +408,11 @@ MultipleOutputs::Close() noexcept
|
|||||||
ao->LockCloseWait();
|
ao->LockCloseWait();
|
||||||
|
|
||||||
if (pipe != nullptr) {
|
if (pipe != nullptr) {
|
||||||
assert(buffer != nullptr);
|
pipe->Clear();
|
||||||
|
|
||||||
pipe->Clear(*buffer);
|
|
||||||
delete pipe;
|
delete pipe;
|
||||||
pipe = nullptr;
|
pipe = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = nullptr;
|
|
||||||
|
|
||||||
input_audio_format.Clear();
|
input_audio_format.Clear();
|
||||||
|
|
||||||
elapsed_time = SignedSongTime::Negative();
|
elapsed_time = SignedSongTime::Negative();
|
||||||
@ -434,15 +425,11 @@ MultipleOutputs::Release() noexcept
|
|||||||
ao->LockRelease();
|
ao->LockRelease();
|
||||||
|
|
||||||
if (pipe != nullptr) {
|
if (pipe != nullptr) {
|
||||||
assert(buffer != nullptr);
|
pipe->Clear();
|
||||||
|
|
||||||
pipe->Clear(*buffer);
|
|
||||||
delete pipe;
|
delete pipe;
|
||||||
pipe = nullptr;
|
pipe = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = nullptr;
|
|
||||||
|
|
||||||
input_audio_format.Clear();
|
input_audio_format.Clear();
|
||||||
|
|
||||||
elapsed_time = SignedSongTime::Negative();
|
elapsed_time = SignedSongTime::Negative();
|
||||||
|
@ -52,11 +52,6 @@ class MultipleOutputs final : public PlayerOutputs {
|
|||||||
|
|
||||||
AudioFormat input_audio_format = AudioFormat::Undefined();
|
AudioFormat input_audio_format = AudioFormat::Undefined();
|
||||||
|
|
||||||
/**
|
|
||||||
* The #MusicBuffer object where consumed chunks are returned.
|
|
||||||
*/
|
|
||||||
MusicBuffer *buffer = nullptr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The #MusicPipe object which feeds all audio outputs. It is
|
* The #MusicPipe object which feeds all audio outputs. It is
|
||||||
* filled by Play().
|
* filled by Play().
|
||||||
|
@ -170,7 +170,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClearAndDeletePipe() noexcept {
|
void ClearAndDeletePipe() noexcept {
|
||||||
pipe->Clear(buffer);
|
pipe->Clear();
|
||||||
delete pipe;
|
delete pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ Player::StartDecoder(MusicPipe &_pipe) noexcept
|
|||||||
|
|
||||||
dc.Start(std::make_unique<DetachedSong>(*pc.next_song),
|
dc.Start(std::make_unique<DetachedSong>(*pc.next_song),
|
||||||
start_time, pc.next_song->GetEndTime(),
|
start_time, pc.next_song->GetEndTime(),
|
||||||
buffer, _pipe);
|
_pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -361,7 +361,7 @@ Player::StopDecoder() noexcept
|
|||||||
if (dc.pipe != nullptr) {
|
if (dc.pipe != nullptr) {
|
||||||
/* clear and free the decoder pipe */
|
/* clear and free the decoder pipe */
|
||||||
|
|
||||||
dc.pipe->Clear(buffer);
|
dc.pipe->Clear();
|
||||||
|
|
||||||
if (dc.pipe != pipe)
|
if (dc.pipe != pipe)
|
||||||
delete dc.pipe;
|
delete dc.pipe;
|
||||||
@ -585,7 +585,7 @@ Player::SeekDecoder() noexcept
|
|||||||
|
|
||||||
/* clear music chunks which might still reside in the
|
/* clear music chunks which might still reside in the
|
||||||
pipe */
|
pipe */
|
||||||
pipe->Clear(buffer);
|
pipe->Clear();
|
||||||
|
|
||||||
/* re-start the decoder */
|
/* re-start the decoder */
|
||||||
StartDecoder(*pipe);
|
StartDecoder(*pipe);
|
||||||
@ -666,7 +666,7 @@ Player::ProcessCommand() noexcept
|
|||||||
pc.CommandFinished();
|
pc.CommandFinished();
|
||||||
|
|
||||||
if (dc.IsIdle())
|
if (dc.IsIdle())
|
||||||
StartDecoder(*new MusicPipe());
|
StartDecoder(*new MusicPipe(buffer));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -939,7 +939,7 @@ Player::SongBorder() noexcept
|
|||||||
inline void
|
inline void
|
||||||
Player::Run() noexcept
|
Player::Run() noexcept
|
||||||
{
|
{
|
||||||
pipe = new MusicPipe();
|
pipe = new MusicPipe(buffer);
|
||||||
|
|
||||||
const std::lock_guard<Mutex> lock(pc.mutex);
|
const std::lock_guard<Mutex> lock(pc.mutex);
|
||||||
|
|
||||||
@ -986,7 +986,7 @@ Player::Run() noexcept
|
|||||||
|
|
||||||
assert(dc.pipe == nullptr || dc.pipe == pipe);
|
assert(dc.pipe == nullptr || dc.pipe == pipe);
|
||||||
|
|
||||||
StartDecoder(*new MusicPipe());
|
StartDecoder(*new MusicPipe(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/* no cross-fading if MPD is going to pause at the
|
if (/* no cross-fading if MPD is going to pause at the
|
||||||
|
Loading…
Reference in New Issue
Block a user