Skip to content

Commit

Permalink
Skip frames up to seek point in Symphonia decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobstern committed Aug 25, 2023
1 parent 8a33286 commit 10b989a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 32 deletions.
82 changes: 51 additions & 31 deletions decode_symphonia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ pub struct SymphoniaDecoder {

num_frames: usize,
num_channels: usize,
sample_rate: Option<u32>,
block_size: usize,

current_frame: usize,
reset_smp_buffer: bool,

seek_delta: usize,
default_track_id: u32,
}

impl Decoder for SymphoniaDecoder {
Expand Down Expand Up @@ -81,28 +83,27 @@ impl Decoder for SymphoniaDecoder {
..Default::default()
};

let params = {
// Get the default stream.
let stream = reader
.default_track()
.ok_or_else(|| OpenError::NoDefaultTrack)?;
let default_track = reader
.default_track()
.ok_or_else(|| OpenError::NoDefaultTrack)?;
let track_id = default_track.id;
let params = default_track.codec_params.clone();

stream.codec_params.clone()
};
let num_frames = params.n_frames.ok_or_else(|| OpenError::NoNumFrames)? as usize;
let sample_rate = params.sample_rate;

let mut seek_delta = 0_usize;

// Seek the reader to the requested position.
if start_frame != 0 {
let seconds = start_frame as f64 / f64::from(sample_rate.unwrap_or(44100));

reader.seek(
let res = reader.seek(
SeekMode::Accurate,
SeekTo::Time {
time: seconds.into(),
track_id: None,
SeekTo::TimeStamp {
ts: start_frame as u64,
track_id,
},
)?;
seek_delta = start_frame - res.actual_ts as usize;
}

// Create a decoder for the stream.
Expand Down Expand Up @@ -132,16 +133,24 @@ impl Decoder for SymphoniaDecoder {
channels = Some(spec.channels);
}

// Get the buffer capacity.
let capacity = decoded.capacity() as u64;
let decoded_frames = decoded.frames();
if seek_delta < decoded_frames {
// Get the buffer capacity.
let capacity = decoded.capacity() as u64;

let mut smp_buf = SampleBuffer::<f32>::new(capacity, spec);
let mut smp_buf = SampleBuffer::<f32>::new(capacity, spec);

smp_buf.copy_interleaved_ref(decoded);
smp_buf.copy_interleaved_ref(decoded);

break smp_buf;
break smp_buf;
} else {
// Continue decoding to seek point
seek_delta -= decoded_frames;
}
}
Err(Error::DecodeError(err)) => {
// If we skipped a packet, the seek delta is probably no longer relevant
seek_delta = 0;
// Decode errors are not fatal.
log::warn!("{err}");
// Continue by decoding the next packet.
Expand All @@ -167,21 +176,24 @@ impl Decoder for SymphoniaDecoder {
num_channels: num_channels as u16,
sample_rate,
};

Ok((
Self {
reader,
decoder,

smp_buf,
curr_smp_buf_i: 0,
curr_smp_buf_i: seek_delta * num_channels,

num_frames,
num_channels,
sample_rate,
block_size,

current_frame: start_frame,
reset_smp_buffer: false,

seek_delta: 0,
default_track_id: track_id,
},
file_info,
))
Expand All @@ -197,16 +209,17 @@ impl Decoder for SymphoniaDecoder {

self.current_frame = frame;

let seconds = self.current_frame as f64 / f64::from(self.sample_rate.unwrap_or(44100));

match self.reader.seek(
SeekMode::Accurate,
SeekTo::Time {
time: seconds.into(),
track_id: None,
SeekTo::TimeStamp {
ts: frame as u64,
track_id: self.default_track_id,
},
) {
Ok(_res) => {}
Ok(res) => {
self.seek_delta = frame - res.actual_ts as usize;
self.decoder.reset();
}
Err(e) => {
return Err(e);
}
Expand Down Expand Up @@ -296,15 +309,22 @@ impl Decoder for SymphoniaDecoder {
}
} else {
// Decode more packets.

loop {
match self.reader.next_packet() {
Ok(packet) => {
match self.decoder.decode(&packet) {
Ok(decoded) => {
self.smp_buf.copy_interleaved_ref(decoded);
self.curr_smp_buf_i = 0;
break;
let seek_delta = self.seek_delta;
let decoded_frames = decoded.frames();
if seek_delta < decoded_frames {
self.seek_delta = 0;
self.smp_buf.copy_interleaved_ref(decoded);
self.curr_smp_buf_i = seek_delta * self.num_channels;
break;
} else {
// Continue until we decode back to the desired seek point
self.seek_delta -= decoded_frames;
}
}
Err(Error::DecodeError(err)) => {
// Decode errors are not fatal.
Expand Down
2 changes: 1 addition & 1 deletion demos/player/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
creek = { path = "../../" }
creek = { path = "../../", features = ["decode-mp3"] }
eframe = "0.9.0"
rtrb = "0.2"
cpal = "0.13"

0 comments on commit 10b989a

Please sign in to comment.