Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: add pts, dts #347

Open
wants to merge 2 commits into
base: dev-0.6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 55 additions & 22 deletions symphonia-core/src/formats/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,11 +481,16 @@ fn matches_track_type(track: &Track, track_type: TrackType) -> bool {
pub struct Packet {
/// The track ID.
track_id: u32,
/// The timestamp of the packet. When gapless support is enabled, this timestamp is relative to
/// the end of the encoder delay.
/// The presentation timestamp (PTS) of the packet. For audio packets, when gapless support is enabled,
/// this timestamp is relative to the end of the encoder delay.
///
/// This timestamp is in `TimeBase` units.
pub ts: u64,
pub pts: u64,
/// The decoding timestamp (DTS) of the packet. Primarily used for video packets and is typically different
/// from the PTS. Can be negative. For audio packets, the DTS is always equal to the PTS
///
/// This timestamp is in `TimeBase` units.
pub dts: i64,
/// The duration of the packet. When gapless support is enabled, the duration does not include
/// the encoder delay or padding.
///
Expand All @@ -503,50 +508,77 @@ pub struct Packet {

impl Packet {
/// Create a new `Packet` from a slice.
pub fn new_from_slice(track_id: u32, ts: u64, dur: u64, buf: &[u8]) -> Self {
Packet { track_id, ts, dur, trim_start: 0, trim_end: 0, data: Box::from(buf) }
pub fn new_from_slice(track_id: u32, pts: u64, dur: u64, buf: &[u8]) -> Self {
Packet {
track_id,
pts,
dts: pts as i64,
dur,
trim_start: 0,
trim_end: 0,
data: Box::from(buf),
}
}

/// Create a new `Packet` from a boxed slice.
pub fn new_from_boxed_slice(track_id: u32, ts: u64, dur: u64, data: Box<[u8]>) -> Self {
Packet { track_id, ts, dur, trim_start: 0, trim_end: 0, data }
pub fn new_from_boxed_slice(track_id: u32, pts: u64, dur: u64, data: Box<[u8]>) -> Self {
Packet { track_id, pts, dts: pts as i64, dur, trim_start: 0, trim_end: 0, data }
}

/// Create a new `Packet` from a boxed slice.
pub fn new_from_boxed_slice_v(
track_id: u32,
pts: u64,
dts: i64,
dur: u64,
data: Box<[u8]>,
) -> Self {
Packet { track_id, pts, dts, dur, trim_start: 0, trim_end: 0, data }
}

/// Create a new `Packet` with trimming information from a slice.
pub fn new_trimmed_from_slice(
track_id: u32,
ts: u64,
pts: u64,
dur: u64,
trim_start: u32,
trim_end: u32,
buf: &[u8],
) -> Self {
Packet { track_id, ts, dur, trim_start, trim_end, data: Box::from(buf) }
Packet { track_id, pts, dts: pts as i64, dur, trim_start, trim_end, data: Box::from(buf) }
}

/// Create a new `Packet` with trimming information from a boxed slice.
pub fn new_trimmed_from_boxed_slice(
track_id: u32,
ts: u64,
pts: u64,
dur: u64,
trim_start: u32,
trim_end: u32,
data: Box<[u8]>,
) -> Self {
Packet { track_id, ts, dur, trim_start, trim_end, data }
Packet { track_id, pts, dts: pts as i64, dur, trim_start, trim_end, data }
}

/// The track identifier of the track this packet belongs to.
pub fn track_id(&self) -> u32 {
self.track_id
}

/// Get the timestamp of the packet in `TimeBase` units.
/// Get the presentation timestamp (PTS) of the packet in `TimeBase` units.
///
/// For audio packets, when gapless support is enabled,
/// this timestamp is relative to the end of the encoder delay.
pub fn pts(&self) -> u64 {
self.pts
}

/// Get the decoding timestamp (DTS) of the packet in `TimeBase` units.
///
/// If gapless support is enabled, then this timestamp is relative to the end of the encoder
/// delay.
pub fn ts(&self) -> u64 {
self.ts
/// Primarily used for video packets and is typically different
/// from the PTS. Can be negative. For audio packets, the DTS is always equal to the PTS
pub fn dts(&self) -> i64 {
self.dts
}

/// Get the duration of the packet in `TimeBase` units.
Expand Down Expand Up @@ -720,20 +752,21 @@ pub mod util {
/// Given a `Packet`, the encoder delay in frames, and the number of non-delay or padding
/// frames, adjust the packet's timestamp and duration, and populate the trim information.
pub fn trim_packet(packet: &mut Packet, delay: u32, num_frames: Option<u64>) {
packet.trim_start = if packet.ts < u64::from(delay) {
let trim = (u64::from(delay) - packet.ts).min(packet.dur);
packet.ts = 0;
packet.trim_start = if packet.pts < u64::from(delay) {
let trim = (u64::from(delay) - packet.pts).min(packet.dur);
packet.pts = 0;
packet.dts = 0;
packet.dur -= trim;
trim as u32
}
else {
packet.ts -= u64::from(delay);
packet.pts -= u64::from(delay);
0
};

if let Some(num_frames) = num_frames {
packet.trim_end = if packet.ts + packet.dur > num_frames {
let trim = (packet.ts + packet.dur - num_frames).min(packet.dur);
packet.trim_end = if packet.pts + packet.dur > num_frames {
let trim = (packet.pts + packet.dur - num_frames).min(packet.dur);
packet.dur -= trim;
trim as u32
}
Expand Down
4 changes: 2 additions & 2 deletions symphonia-format-ogg/src/demuxer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ impl<'s> OggReader<'s> {
let actual_ts = loop {
match self.peek_logical_packet() {
Some(packet) => {
if packet.track_id() == serial && packet.ts + packet.dur >= required_ts {
break packet.ts;
if packet.track_id() == serial && packet.pts + packet.dur >= required_ts {
break packet.pts;
}

self.discard_logical_packet();
Expand Down
3 changes: 2 additions & 1 deletion symphonia-format-ogg/src/logical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ impl LogicalStream {

for packet in self.packets.iter_mut().rev().take(num_new_packets) {
page_dur = page_dur.saturating_add(packet.dur);
packet.ts = page_end_ts.saturating_sub(page_dur);
packet.pts = page_end_ts.saturating_sub(page_dur);
packet.dts = packet.pts as i64;
}

if self.gapless {
Expand Down
4 changes: 2 additions & 2 deletions symphonia-play/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,9 +470,9 @@ fn play_track(
// should be decoded and *samples* discarded up-to the exact *sample* indicated by
// required_ts. The current approach will discard extra samples if seeking to a
// sample within a packet.
if packet.ts() >= opts.seek_ts {
if packet.pts() >= opts.seek_ts {
if !opts.no_progress {
ui::print_progress(packet.ts(), dur, tb);
ui::print_progress(packet.pts(), dur, tb);
}

if let Some(audio_output) = audio_output {
Expand Down
Loading