From 5d44f910f3fe00e0ab5e3427da008594b78902df Mon Sep 17 00:00:00 2001 From: Philip Deljanov Date: Wed, 5 Jan 2022 00:03:54 -0500 Subject: [PATCH] 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. --- playback/src/decoder/symphonia_decoder.rs | 67 ++++++++++++----------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/playback/src/decoder/symphonia_decoder.rs b/playback/src/decoder/symphonia_decoder.rs index 3b585007..fa096ade 100644 --- a/playback/src/decoder/symphonia_decoder.rs +++ b/playback/src/decoder/symphonia_decoder.rs @@ -171,43 +171,44 @@ impl AudioDecoder for SymphoniaDecoder { } fn next_packet(&mut self) -> DecoderResult> { - let packet = match self.format.next_packet() { - Ok(packet) => packet, - Err(Error::IoError(err)) => { - if err.kind() == io::ErrorKind::UnexpectedEof { - return Ok(None); - } else { - return Err(DecoderError::SymphoniaDecoder(err.to_string())); + loop { + let packet = match self.format.next_packet() { + Ok(packet) => packet, + Err(Error::IoError(err)) => { + if err.kind() == io::ErrorKind::UnexpectedEof { + return Ok(None); + } else { + return Err(DecoderError::SymphoniaDecoder(err.to_string())); + } } - } - Err(Error::ResetRequired) => { - 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)); + Err(err) => { + return Err(err.into()); } + }; - 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()); - Ok(Some((position_ms, samples))) + 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 + 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()), } } }