mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Handle format reset and decode errors.
This change fixes two issues with the error handling of the Symphonia decode loop. 1) `Error::ResetRequired` should always be propagated to jump to the next Spotify track. 2) On a decode error, get a new packet and try again instead of propagating the error and jumping to the next track.
This commit is contained in:
parent
3e09eff906
commit
5d44f910f3
1 changed files with 34 additions and 33 deletions
|
@ -171,43 +171,44 @@ impl AudioDecoder for SymphoniaDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_packet(&mut self) -> DecoderResult<Option<(u32, AudioPacket)>> {
|
fn next_packet(&mut self) -> DecoderResult<Option<(u32, AudioPacket)>> {
|
||||||
let packet = match self.format.next_packet() {
|
loop {
|
||||||
Ok(packet) => packet,
|
let packet = match self.format.next_packet() {
|
||||||
Err(Error::IoError(err)) => {
|
Ok(packet) => packet,
|
||||||
if err.kind() == io::ErrorKind::UnexpectedEof {
|
Err(Error::IoError(err)) => {
|
||||||
return Ok(None);
|
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||||
} else {
|
return Ok(None);
|
||||||
return Err(DecoderError::SymphoniaDecoder(err.to_string()));
|
} else {
|
||||||
|
return Err(DecoderError::SymphoniaDecoder(err.to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(err) => {
|
||||||
Err(Error::ResetRequired) => {
|
return Err(err.into());
|
||||||
self.decoder.reset();
|
|
||||||
return self.next_packet();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return Err(err.into());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let position_ms = self.ts_to_ms(packet.pts());
|
|
||||||
|
|
||||||
match self.decoder.decode(&packet) {
|
|
||||||
Ok(decoded) => {
|
|
||||||
if self.sample_buffer.is_none() {
|
|
||||||
let spec = *decoded.spec();
|
|
||||||
let duration = decoded.capacity() as u64;
|
|
||||||
self.sample_buffer
|
|
||||||
.replace(SampleBuffer::new(duration, spec));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let sample_buffer = self.sample_buffer.as_mut().unwrap(); // guaranteed above
|
let position_ms = self.ts_to_ms(packet.pts());
|
||||||
sample_buffer.copy_interleaved_ref(decoded);
|
|
||||||
let samples = AudioPacket::Samples(sample_buffer.samples().to_vec());
|
match self.decoder.decode(&packet) {
|
||||||
Ok(Some((position_ms, samples)))
|
Ok(decoded) => {
|
||||||
|
if self.sample_buffer.is_none() {
|
||||||
|
let spec = *decoded.spec();
|
||||||
|
let duration = decoded.capacity() as u64;
|
||||||
|
self.sample_buffer
|
||||||
|
.replace(SampleBuffer::new(duration, spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
let sample_buffer = self.sample_buffer.as_mut().unwrap(); // guaranteed above
|
||||||
|
sample_buffer.copy_interleaved_ref(decoded);
|
||||||
|
let samples = AudioPacket::Samples(sample_buffer.samples().to_vec());
|
||||||
|
return Ok(Some((position_ms, samples)));
|
||||||
|
}
|
||||||
|
Err(Error::DecodeError(_)) => {
|
||||||
|
// The packet failed to decode due to corrupted or invalid data, get a new
|
||||||
|
// packet and try again.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(err) => return Err(err.into()),
|
||||||
}
|
}
|
||||||
// Also propagate `ResetRequired` errors from the decoder to the player,
|
|
||||||
// so that it will skip to the next track and reload the entire Symphonia decoder.
|
|
||||||
Err(err) => Err(err.into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue