output/PipeWire: use class RingBuffer instead of boost::lockfree::spsc_queue
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include "system/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
#include "util/BitReverse.hxx"
|
#include "util/BitReverse.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
#include "util/RingBuffer.hxx"
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
@@ -52,8 +53,6 @@
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/lockfree/spsc_queue.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
@@ -81,8 +80,8 @@ class PipeWireOutput final : AudioOutput {
|
|||||||
/**
|
/**
|
||||||
* This buffer passes PCM data from Play() to Process().
|
* This buffer passes PCM data from Play() to Process().
|
||||||
*/
|
*/
|
||||||
using RingBuffer = boost::lockfree::spsc_queue<std::byte>;
|
using RingBuffer = ::RingBuffer<std::byte>;
|
||||||
RingBuffer *ring_buffer;
|
RingBuffer ring_buffer;
|
||||||
|
|
||||||
uint32_t target_id = PW_ID_ANY;
|
uint32_t target_id = PW_ID_ANY;
|
||||||
|
|
||||||
@@ -572,9 +571,7 @@ PipeWireOutput::Open(AudioFormat &audio_format)
|
|||||||
interrupted = false;
|
interrupted = false;
|
||||||
|
|
||||||
/* allocate a ring buffer of 0.5 seconds */
|
/* allocate a ring buffer of 0.5 seconds */
|
||||||
const std::size_t ring_buffer_size =
|
ring_buffer = RingBuffer{frame_size * (audio_format.sample_rate / 2)};
|
||||||
frame_size * (audio_format.sample_rate / 2);
|
|
||||||
ring_buffer = new RingBuffer(ring_buffer_size);
|
|
||||||
|
|
||||||
const struct spa_pod *params[1];
|
const struct spa_pod *params[1];
|
||||||
|
|
||||||
@@ -626,7 +623,7 @@ PipeWireOutput::Close() noexcept
|
|||||||
stream = nullptr;
|
stream = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete ring_buffer;
|
ring_buffer = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@@ -774,25 +771,17 @@ PipeWireOutput::Process() noexcept
|
|||||||
if (dest == nullptr)
|
if (dest == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::size_t max_frames = d.maxsize / frame_size;
|
std::size_t chunk_size = frame_size;
|
||||||
|
|
||||||
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
|
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
|
||||||
if (use_dsd && dsd_interleave > 1) {
|
if (use_dsd && dsd_interleave > 1) {
|
||||||
/* make sure we don't get partial interleave frames */
|
/* make sure we don't get partial interleave frames */
|
||||||
std::size_t interleave_size = frame_size * dsd_interleave;
|
chunk_size *= dsd_interleave;
|
||||||
std::size_t available_bytes = ring_buffer->read_available();
|
|
||||||
std::size_t available_interleaves =
|
|
||||||
available_bytes / interleave_size;
|
|
||||||
std::size_t available_frames =
|
|
||||||
available_interleaves * dsd_interleave;
|
|
||||||
if (max_frames > available_frames)
|
|
||||||
max_frames = available_frames;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::size_t max_size = max_frames * frame_size;
|
size_t nbytes = ring_buffer.ReadFramesTo({dest, d.maxsize}, chunk_size);
|
||||||
size_t nbytes = ring_buffer->pop(dest, max_size);
|
assert(nbytes % chunk_size == 0);
|
||||||
assert(nbytes % frame_size == 0);
|
|
||||||
if (nbytes == 0) {
|
if (nbytes == 0) {
|
||||||
if (drain_requested) {
|
if (drain_requested) {
|
||||||
pw_stream_flush(stream, true);
|
pw_stream_flush(stream, true);
|
||||||
@@ -800,8 +789,9 @@ PipeWireOutput::Process() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* buffer underrun: generate some silence */
|
/* buffer underrun: generate some silence */
|
||||||
PcmSilence({dest, max_size}, sample_format);
|
std::size_t max_chunks = d.maxsize / chunk_size;
|
||||||
nbytes = max_size;
|
nbytes = max_chunks * chunk_size;
|
||||||
|
PcmSilence({dest, nbytes}, sample_format);
|
||||||
|
|
||||||
LogWarning(pipewire_output_domain, "Decoder is too slow; playing silence to avoid xrun");
|
LogWarning(pipewire_output_domain, "Decoder is too slow; playing silence to avoid xrun");
|
||||||
}
|
}
|
||||||
@@ -846,7 +836,7 @@ PipeWireOutput::Play(std::span<const std::byte> src)
|
|||||||
CheckThrowError();
|
CheckThrowError();
|
||||||
|
|
||||||
std::size_t bytes_written =
|
std::size_t bytes_written =
|
||||||
ring_buffer->push(src.data(), src.size());
|
ring_buffer.WriteFrom(src);
|
||||||
if (bytes_written > 0) {
|
if (bytes_written > 0) {
|
||||||
drained = false;
|
drained = false;
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
@@ -902,7 +892,7 @@ PipeWireOutput::Cancel() noexcept
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* clear MPD's ring buffer */
|
/* clear MPD's ring buffer */
|
||||||
ring_buffer->reset();
|
ring_buffer.Clear();
|
||||||
|
|
||||||
/* clear libpipewire's buffer */
|
/* clear libpipewire's buffer */
|
||||||
pw_stream_flush(stream, false);
|
pw_stream_flush(stream, false);
|
||||||
|
Reference in New Issue
Block a user