Skip to content

Commit

Permalink
Refine latency calculations in Pump
Browse files Browse the repository at this point in the history
  • Loading branch information
gavv committed Sep 10, 2023
1 parent adadd99 commit 0cd208e
Show file tree
Hide file tree
Showing 28 changed files with 133 additions and 19 deletions.
8 changes: 8 additions & 0 deletions src/internal_modules/roc_pipeline/receiver_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ core::nanoseconds_t ReceiverLoop::latency() const {
return source_.latency();
}

bool ReceiverLoop::has_latency() const {
roc_panic_if(!is_valid());

core::Mutex::Lock lock(source_mutex_);

return source_.has_latency();
}

bool ReceiverLoop::has_clock() const {
roc_panic_if(!is_valid());

Expand Down
1 change: 1 addition & 0 deletions src/internal_modules/roc_pipeline/receiver_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class ReceiverLoop : public PipelineLoop, private sndio::ISource {
virtual bool restart();
virtual audio::SampleSpec sample_spec() const;
virtual core::nanoseconds_t latency() const;
virtual bool has_latency() const;
virtual bool has_clock() const;
virtual void reclock(core::nanoseconds_t timestamp);
virtual bool read(audio::Frame&);
Expand Down
4 changes: 4 additions & 0 deletions src/internal_modules/roc_pipeline/receiver_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ core::nanoseconds_t ReceiverSource::latency() const {
return 0;
}

bool ReceiverSource::has_latency() const {
return false;
}

bool ReceiverSource::has_clock() const {
return config_.common.enable_timing;
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_pipeline/receiver_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class ReceiverSource : public sndio::ISource, public core::NonCopyable<> {
//! Get latency of the source.
virtual core::nanoseconds_t latency() const;

//! Check if the source supports latency reports.
virtual bool has_latency() const;

//! Check if the source has own clock.
virtual bool has_clock() const;

Expand Down
8 changes: 8 additions & 0 deletions src/internal_modules/roc_pipeline/sender_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ core::nanoseconds_t SenderLoop::latency() const {
return sink_.latency();
}

bool SenderLoop::has_latency() const {
roc_panic_if_not(is_valid());

core::Mutex::Lock lock(sink_mutex_);

return sink_.has_latency();
}

bool SenderLoop::has_clock() const {
roc_panic_if_not(is_valid());

Expand Down
1 change: 1 addition & 0 deletions src/internal_modules/roc_pipeline/sender_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class SenderLoop : public PipelineLoop, private sndio::ISink {
virtual bool restart();
virtual audio::SampleSpec sample_spec() const;
virtual core::nanoseconds_t latency() const;
virtual bool has_latency() const;
virtual bool has_clock() const;
virtual void write(audio::Frame& frame);

Expand Down
4 changes: 4 additions & 0 deletions src/internal_modules/roc_pipeline/sender_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ core::nanoseconds_t SenderSink::latency() const {
return 0;
}

bool SenderSink::has_latency() const {
return false;
}

bool SenderSink::has_clock() const {
return config_.enable_timing;
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_pipeline/sender_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class SenderSink : public sndio::ISink, public core::NonCopyable<> {
//! Get latency of the sink.
virtual core::nanoseconds_t latency() const;

//! Check if the sink supports latency reports.
virtual bool has_latency() const;

//! Check if the sink has own clock.
virtual bool has_clock() const;

Expand Down
4 changes: 4 additions & 0 deletions src/internal_modules/roc_pipeline/transcoder_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ core::nanoseconds_t TranscoderSink::latency() const {
return 0;
}

bool TranscoderSink::has_latency() const {
return false;
}

bool TranscoderSink::has_clock() const {
return false;
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_pipeline/transcoder_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class TranscoderSink : public sndio::ISink, public core::NonCopyable<> {
//! Get latency of the sink.
virtual core::nanoseconds_t latency() const;

//! Check if the sink supports latency reports.
virtual bool has_latency() const;

//! Check if the sink has own clock.
virtual bool has_clock() const;

Expand Down
4 changes: 4 additions & 0 deletions src/internal_modules/roc_pipeline/transcoder_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ core::nanoseconds_t TranscoderSource::latency() const {
return 0;
}

bool TranscoderSource::has_latency() const {
return false;
}

bool TranscoderSource::has_clock() const {
return input_source_.has_clock();
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_pipeline/transcoder_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class TranscoderSource : public sndio::ISource, public core::NonCopyable<> {
//! Get latency of the source.
virtual core::nanoseconds_t latency() const;

//! Check if the source supports latency reports.
virtual bool has_latency() const;

//! Check if the sink has own clock.
virtual bool has_clock() const;

Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_sndio/idevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class IDevice {
//! Get latency of the device.
virtual core::nanoseconds_t latency() const = 0;

//! Check if the device supports latency reports.
virtual bool has_latency() const = 0;

//! Check if the device has own clock.
virtual bool has_clock() const = 0;
};
Expand Down
36 changes: 26 additions & 10 deletions src/internal_modules/roc_sndio/pump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ bool Pump::run() {
ISource* current_source = &main_source_;

while (!stop_) {
// switch between main and backup sources when necessary
if (main_source_.state() == DeviceState_Active) {
if (current_source == backup_source_) {
roc_log(LogInfo, "pump: switching to main source");
Expand Down Expand Up @@ -86,6 +87,7 @@ bool Pump::run() {
}
}

// read frame
audio::Frame frame(frame_buffer_.data(), frame_buffer_.size());

// if source has clock, here we block on it
Expand All @@ -106,21 +108,35 @@ bool Pump::run() {
// where this frame spent some time before we read it
// we subtract frame size because we already read the whole frame from
// recording buffer, and should take it into account too
frame.set_capture_timestamp(
core::timestamp(core::ClockUnix) - current_source->latency()
- sample_spec_.samples_overall_2_ns(frame.num_samples()));
core::nanoseconds_t capture_latency = 0;

if (current_source->has_latency()) {
capture_latency = current_source->latency()
+ sample_spec_.samples_overall_2_ns(frame.num_samples());
}

frame.set_capture_timestamp(core::timestamp(core::ClockUnix)
- capture_latency);
}

// if sink has clock, here we block on it
// note that either source or sink may have clock, but not both
// note that either source or sink has clock, but not both
sink_.write(frame);

// tell source what is playback time of first sample of last read frame
// we add sink latency to take into account playback buffer size
// we subtract frame size because we already wrote the whole frame into
// playback buffer, and should take it into account too
current_source->reclock(core::timestamp(core::ClockUnix) + sink_.latency()
- sample_spec_.samples_overall_2_ns(frame.num_samples()));
{
// tell source what is playback time of first sample of last read frame
// we add sink latency to take into account playback buffer size
// we subtract frame size because we already wrote the whole frame into
// playback buffer, and should take it into account too
core::nanoseconds_t playback_latency = 0;

if (sink_.has_latency()) {
playback_latency = sink_.latency()
- sample_spec_.samples_overall_2_ns(frame.num_samples());
}

current_source->reclock(core::timestamp(core::ClockUnix) + playback_latency);
}

if (current_source == &main_source_) {
n_bufs_++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,6 @@ core::nanoseconds_t PulseaudioDevice::latency() const {
return latency;
}

bool PulseaudioDevice::has_clock() const {
return true;
}

bool PulseaudioDevice::request(audio::Frame& frame) {
want_mainloop_();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ class PulseaudioDevice : public core::NonCopyable<> {
//! Get latency of the sink.
core::nanoseconds_t latency() const;

//! Check if the sink has own clock.
bool has_clock() const;

//! Process audio frame.
bool request(audio::Frame& frame);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ core::nanoseconds_t PulseaudioSink::latency() const {
return PulseaudioDevice::latency();
}

bool PulseaudioSink::has_latency() const {
return true;
}

bool PulseaudioSink::has_clock() const {
return PulseaudioDevice::has_clock();
return true;
}

void PulseaudioSink::write(audio::Frame& frame) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class PulseaudioSink : public ISink, public PulseaudioDevice {
//! Get latency of the sink.
virtual core::nanoseconds_t latency() const;

//! Check if the sink supports latency reports.
virtual bool has_latency() const;

//! Check if the sink has own clock.
virtual bool has_clock() const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ core::nanoseconds_t PulseaudioSource::latency() const {
return PulseaudioDevice::latency();
}

bool PulseaudioSource::has_latency() const {
return true;
}

bool PulseaudioSource::has_clock() const {
return PulseaudioDevice::has_clock();
return true;
}

void PulseaudioSource::reclock(core::nanoseconds_t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class PulseaudioSource : public ISource, public PulseaudioDevice {
//! Get latency of the source.
virtual core::nanoseconds_t latency() const;

//! Check if the source supports latency reports.
virtual bool has_latency() const;

//! Check if the source has own clock.
virtual bool has_clock() const;

Expand Down
10 changes: 10 additions & 0 deletions src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ core::nanoseconds_t SoxSink::latency() const {
return 0;
}

bool SoxSink::has_latency() const {
roc_panic_if(!valid_);

if (!output_) {
roc_panic("sox sink: has_latency(): non-open output file or device");
}

return false;
}

bool SoxSink::has_clock() const {
roc_panic_if(!valid_);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class SoxSink : public ISink, public core::NonCopyable<> {
//! Get latency of the sink.
virtual core::nanoseconds_t latency() const;

//! Check if the sink supports latency reports.
virtual bool has_latency() const;

//! Check if the sink has own clock.
virtual bool has_clock() const;

Expand Down
10 changes: 10 additions & 0 deletions src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ core::nanoseconds_t SoxSource::latency() const {
return 0;
}

bool SoxSource::has_latency() const {
roc_panic_if(!valid_);

if (!input_) {
roc_panic("sox source: has_latency(): non-open input file or device");
}

return false;
}

bool SoxSource::has_clock() const {
roc_panic_if(!valid_);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class SoxSource : public ISource, private core::NonCopyable<> {
//! Get latency of the source.
virtual core::nanoseconds_t latency() const;

//! Check if the source supports latency reports.
virtual bool has_latency() const;

//! Check if the source has own clock.
virtual bool has_clock() const;

Expand Down
4 changes: 4 additions & 0 deletions src/tests/roc_pipeline/test_helpers/mock_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class MockSink : public sndio::ISink, public core::NonCopyable<> {
return 0;
}

virtual bool has_latency() const {
return false;
}

virtual bool has_clock() const {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/tests/roc_pipeline/test_helpers/mock_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class MockSource : public sndio::ISource {
return 0;
}

virtual bool has_latency() const {
return false;
}

virtual bool has_clock() const {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/tests/roc_sndio/target_sox/test_helpers/mock_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class MockSink : public ISink {
return 0;
}

virtual bool has_latency() const {
return false;
}

virtual bool has_clock() const {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/tests/roc_sndio/target_sox/test_helpers/mock_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class MockSource : public ISource {
return 0;
}

virtual bool has_latency() const {
return false;
}

virtual bool has_clock() const {
return false;
}
Expand Down

0 comments on commit 0cd208e

Please sign in to comment.