mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Update notify_about_position logic
It would be so much easier to use elapsed but elapsed could potentially panic is rare cases. See: https://doc.rust-lang.org/std/time/struct.Instant.html#monotonicity Otherwise this is pretty straight forward. If anything fails getting expected_position_ms it will return 0 which will trigger a notify if either stream_position_ms or decoder_position_ms is > 1000. If all goes well it's simply a matter of calculating the max delta of expected_position_ms and stream_position_ms and expected_position_ms and decoder_position_ms. So if the decoder or the sample pipeline are off by more than 1 sec we notify.
This commit is contained in:
parent
09bd1bd324
commit
8d35b4b860
1 changed files with 38 additions and 48 deletions
|
@ -1150,68 +1150,58 @@ impl Future for PlayerInternal {
|
||||||
match decoder.next_packet() {
|
match decoder.next_packet() {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
if let Some((ref packet_position, ref packet)) = result {
|
if let Some((ref packet_position, ref packet)) = result {
|
||||||
let new_stream_position_ms = packet_position
|
let decoder_position_ms = packet_position.position_ms;
|
||||||
.position_ms
|
|
||||||
.saturating_sub(sample_pipeline_latency_ms);
|
|
||||||
|
|
||||||
let expected_position_ms = std::mem::replace(
|
*stream_position_ms =
|
||||||
&mut *stream_position_ms,
|
decoder_position_ms.saturating_sub(sample_pipeline_latency_ms);
|
||||||
new_stream_position_ms,
|
|
||||||
);
|
|
||||||
|
|
||||||
if !passthrough {
|
if !passthrough {
|
||||||
match packet.samples() {
|
match packet.samples() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let new_stream_position = Duration::from_millis(
|
|
||||||
new_stream_position_ms as u64,
|
|
||||||
);
|
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
// Only notify if we're skipped some packets *or* we are behind.
|
let notify_about_position = {
|
||||||
// If we're ahead it's probably due to a buffer of the backend
|
// It would be so much easier to use elapsed but elapsed could
|
||||||
// and we're actually in time.
|
// potentially panic is rare cases.
|
||||||
let notify_about_position =
|
// See:
|
||||||
match *reported_nominal_start_time {
|
// https://doc.rust-lang.org/std/time/struct.Instant.html#monotonicity
|
||||||
None => true,
|
//
|
||||||
Some(reported_nominal_start_time) => {
|
// Otherwise this is pretty straight forward. If anything fails getting
|
||||||
let mut notify = false;
|
// expected_position_ms it will return 0 which will trigger a notify if
|
||||||
|
// either stream_position_ms or decoder_position_ms is > 1000. If all goes
|
||||||
|
// well it's simply a matter of calculating the max delta of expected_position_ms
|
||||||
|
// and stream_position_ms and expected_position_ms and decoder_position_ms.
|
||||||
|
// So if the decoder or the sample pipeline are off by more than 1 sec we notify.
|
||||||
|
let expected_position_ms = now
|
||||||
|
.checked_duration_since(
|
||||||
|
reported_nominal_start_time.unwrap_or(now),
|
||||||
|
)
|
||||||
|
.unwrap_or(Duration::ZERO)
|
||||||
|
.as_millis();
|
||||||
|
|
||||||
if packet_position.skipped {
|
let max_expected_position_delta_ms =
|
||||||
if let Some(ahead) = new_stream_position
|
expected_position_ms
|
||||||
.checked_sub(Duration::from_millis(
|
.abs_diff(*stream_position_ms as u128)
|
||||||
expected_position_ms as u64,
|
.max(
|
||||||
))
|
expected_position_ms.abs_diff(
|
||||||
{
|
decoder_position_ms as u128,
|
||||||
notify |=
|
),
|
||||||
ahead >= Duration::from_secs(1)
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(lag) = now
|
max_expected_position_delta_ms > 1000
|
||||||
.checked_duration_since(
|
};
|
||||||
reported_nominal_start_time,
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if let Some(lag) =
|
|
||||||
lag.checked_sub(new_stream_position)
|
|
||||||
{
|
|
||||||
notify |=
|
|
||||||
lag >= Duration::from_secs(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notify || sample_pipeline_latency_ms > 1000
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if notify_about_position {
|
if notify_about_position {
|
||||||
*reported_nominal_start_time =
|
let position_ms = *stream_position_ms;
|
||||||
now.checked_sub(new_stream_position);
|
|
||||||
|
*reported_nominal_start_time = now.checked_sub(
|
||||||
|
Duration::from_millis(position_ms as u64),
|
||||||
|
);
|
||||||
|
|
||||||
self.send_event(PlayerEvent::PositionCorrection {
|
self.send_event(PlayerEvent::PositionCorrection {
|
||||||
play_request_id,
|
play_request_id,
|
||||||
track_id,
|
track_id,
|
||||||
position_ms: new_stream_position_ms,
|
position_ms,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue