mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Fix broken streaming mode
This commit is contained in:
parent
7226bfd55a
commit
4925adb4f1
2 changed files with 46 additions and 52 deletions
|
@ -248,6 +248,7 @@ struct AudioFileShared {
|
||||||
cond: Condvar,
|
cond: Condvar,
|
||||||
download_status: Mutex<AudioFileDownloadStatus>,
|
download_status: Mutex<AudioFileDownloadStatus>,
|
||||||
download_strategy: Mutex<DownloadStrategy>,
|
download_strategy: Mutex<DownloadStrategy>,
|
||||||
|
number_of_open_requests: AtomicUsize,
|
||||||
ping_time_ms: AtomicUsize,
|
ping_time_ms: AtomicUsize,
|
||||||
read_position: AtomicUsize,
|
read_position: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
@ -356,6 +357,7 @@ impl AudioFileStreaming {
|
||||||
downloaded: RangeSet::new(),
|
downloaded: RangeSet::new(),
|
||||||
}),
|
}),
|
||||||
download_strategy: Mutex::new(DownloadStrategy::RandomAccess()), // start with random access mode until someone tells us otherwise
|
download_strategy: Mutex::new(DownloadStrategy::RandomAccess()), // start with random access mode until someone tells us otherwise
|
||||||
|
number_of_open_requests: AtomicUsize::new(0),
|
||||||
ping_time_ms: AtomicUsize::new(0),
|
ping_time_ms: AtomicUsize::new(0),
|
||||||
read_position: AtomicUsize::new(0),
|
read_position: AtomicUsize::new(0),
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,12 +68,16 @@ async fn receive_data(
|
||||||
initial_data_offset: usize,
|
initial_data_offset: usize,
|
||||||
initial_request_length: usize,
|
initial_request_length: usize,
|
||||||
request_sent_time: Instant,
|
request_sent_time: Instant,
|
||||||
mut measure_ping_time: bool,
|
|
||||||
finish_tx: mpsc::UnboundedSender<()>,
|
|
||||||
) {
|
) {
|
||||||
let mut data_offset = initial_data_offset;
|
let mut data_offset = initial_data_offset;
|
||||||
let mut request_length = initial_request_length;
|
let mut request_length = initial_request_length;
|
||||||
|
|
||||||
|
let old_number_of_request = shared
|
||||||
|
.number_of_open_requests
|
||||||
|
.fetch_add(1, atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
|
let mut measure_ping_time = old_number_of_request == 0;
|
||||||
|
|
||||||
let result = loop {
|
let result = loop {
|
||||||
let data = match data_rx.next().await {
|
let data = match data_rx.next().await {
|
||||||
Some(Ok(data)) => data,
|
Some(Ok(data)) => data,
|
||||||
|
@ -121,7 +125,9 @@ async fn receive_data(
|
||||||
shared.cond.notify_all();
|
shared.cond.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = finish_tx.send(());
|
shared
|
||||||
|
.number_of_open_requests
|
||||||
|
.fetch_sub(1, atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -144,9 +150,6 @@ struct AudioFileFetch {
|
||||||
file_data_tx: mpsc::UnboundedSender<ReceivedData>,
|
file_data_tx: mpsc::UnboundedSender<ReceivedData>,
|
||||||
complete_tx: Option<oneshot::Sender<NamedTempFile>>,
|
complete_tx: Option<oneshot::Sender<NamedTempFile>>,
|
||||||
network_response_times_ms: Vec<usize>,
|
network_response_times_ms: Vec<usize>,
|
||||||
number_of_open_requests: usize,
|
|
||||||
|
|
||||||
download_finish_tx: mpsc::UnboundedSender<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might be replaced by enum from std once stable
|
// Might be replaced by enum from std once stable
|
||||||
|
@ -214,11 +217,7 @@ impl AudioFileFetch {
|
||||||
range.start,
|
range.start,
|
||||||
range.length,
|
range.length,
|
||||||
Instant::now(),
|
Instant::now(),
|
||||||
self.number_of_open_requests == 0,
|
|
||||||
self.download_finish_tx.clone(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
self.number_of_open_requests += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +340,6 @@ impl AudioFileFetch {
|
||||||
}
|
}
|
||||||
StreamLoaderCommand::StreamMode() => {
|
StreamLoaderCommand::StreamMode() => {
|
||||||
*(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::Streaming();
|
*(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::Streaming();
|
||||||
self.trigger_preload();
|
|
||||||
}
|
}
|
||||||
StreamLoaderCommand::Close() => return ControlFlow::Break,
|
StreamLoaderCommand::Close() => return ControlFlow::Break,
|
||||||
}
|
}
|
||||||
|
@ -355,36 +353,6 @@ impl AudioFileFetch {
|
||||||
output.seek(SeekFrom::Start(0)).unwrap();
|
output.seek(SeekFrom::Start(0)).unwrap();
|
||||||
let _ = complete_tx.send(output);
|
let _ = complete_tx.send(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_preload(&mut self) {
|
|
||||||
if self.number_of_open_requests >= MAX_PREFETCH_REQUESTS {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let max_requests_to_send = MAX_PREFETCH_REQUESTS - self.number_of_open_requests;
|
|
||||||
|
|
||||||
let bytes_pending: usize = {
|
|
||||||
let download_status = self.shared.download_status.lock().unwrap();
|
|
||||||
download_status
|
|
||||||
.requested
|
|
||||||
.minus(&download_status.downloaded)
|
|
||||||
.len()
|
|
||||||
};
|
|
||||||
|
|
||||||
let ping_time_seconds =
|
|
||||||
0.001 * self.shared.ping_time_ms.load(atomic::Ordering::Relaxed) as f64;
|
|
||||||
let download_rate = self.session.channel().get_download_rate_estimate();
|
|
||||||
|
|
||||||
let desired_pending_bytes = max(
|
|
||||||
(PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * self.shared.stream_data_rate as f64)
|
|
||||||
as usize,
|
|
||||||
(FAST_PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * download_rate as f64) as usize,
|
|
||||||
);
|
|
||||||
|
|
||||||
if bytes_pending < desired_pending_bytes {
|
|
||||||
self.pre_fetch_more_data(desired_pending_bytes - bytes_pending, max_requests_to_send);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn audio_file_fetch(
|
pub(super) async fn audio_file_fetch(
|
||||||
|
@ -399,7 +367,6 @@ pub(super) async fn audio_file_fetch(
|
||||||
complete_tx: oneshot::Sender<NamedTempFile>,
|
complete_tx: oneshot::Sender<NamedTempFile>,
|
||||||
) {
|
) {
|
||||||
let (file_data_tx, mut file_data_rx) = mpsc::unbounded_channel();
|
let (file_data_tx, mut file_data_rx) = mpsc::unbounded_channel();
|
||||||
let (download_finish_tx, mut download_finish_rx) = mpsc::unbounded_channel();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let requested_range = Range::new(0, initial_data_length);
|
let requested_range = Range::new(0, initial_data_length);
|
||||||
|
@ -414,8 +381,6 @@ pub(super) async fn audio_file_fetch(
|
||||||
0,
|
0,
|
||||||
initial_data_length,
|
initial_data_length,
|
||||||
initial_request_sent_time,
|
initial_request_sent_time,
|
||||||
true,
|
|
||||||
download_finish_tx.clone(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut fetch = AudioFileFetch {
|
let mut fetch = AudioFileFetch {
|
||||||
|
@ -426,9 +391,6 @@ pub(super) async fn audio_file_fetch(
|
||||||
file_data_tx,
|
file_data_tx,
|
||||||
complete_tx: Some(complete_tx),
|
complete_tx: Some(complete_tx),
|
||||||
network_response_times_ms: Vec::new(),
|
network_response_times_ms: Vec::new(),
|
||||||
number_of_open_requests: 1,
|
|
||||||
|
|
||||||
download_finish_tx,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -442,12 +404,42 @@ pub(super) async fn audio_file_fetch(
|
||||||
if data.map_or(true, |data| fetch.handle_file_data(data) == ControlFlow::Break) {
|
if data.map_or(true, |data| fetch.handle_file_data(data) == ControlFlow::Break) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ = download_finish_rx.recv() => {
|
}
|
||||||
fetch.number_of_open_requests -= 1;
|
|
||||||
|
|
||||||
if fetch.get_download_strategy() == DownloadStrategy::Streaming() {
|
if fetch.get_download_strategy() == DownloadStrategy::Streaming() {
|
||||||
fetch.trigger_preload();
|
let number_of_open_requests = fetch
|
||||||
|
.shared
|
||||||
|
.number_of_open_requests
|
||||||
|
.load(atomic::Ordering::SeqCst);
|
||||||
|
if number_of_open_requests < MAX_PREFETCH_REQUESTS {
|
||||||
|
let max_requests_to_send = MAX_PREFETCH_REQUESTS - number_of_open_requests;
|
||||||
|
|
||||||
|
let bytes_pending: usize = {
|
||||||
|
let download_status = fetch.shared.download_status.lock().unwrap();
|
||||||
|
download_status
|
||||||
|
.requested
|
||||||
|
.minus(&download_status.downloaded)
|
||||||
|
.len()
|
||||||
|
};
|
||||||
|
|
||||||
|
let ping_time_seconds =
|
||||||
|
0.001 * fetch.shared.ping_time_ms.load(atomic::Ordering::Relaxed) as f64;
|
||||||
|
let download_rate = fetch.session.channel().get_download_rate_estimate();
|
||||||
|
|
||||||
|
let desired_pending_bytes = max(
|
||||||
|
(PREFETCH_THRESHOLD_FACTOR
|
||||||
|
* ping_time_seconds
|
||||||
|
* fetch.shared.stream_data_rate as f64) as usize,
|
||||||
|
(FAST_PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * download_rate as f64)
|
||||||
|
as usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
if bytes_pending < desired_pending_bytes {
|
||||||
|
fetch.pre_fetch_more_data(
|
||||||
|
desired_pending_bytes - bytes_pending,
|
||||||
|
max_requests_to_send,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue