rff_core/packet.rs
1//! A `Packet` is a chunk of *compressed* data for one stream — the unit that
2//! flows demuxer → decoder and encoder → muxer. Analogous to `AVPacket`.
3
4use crate::rational::Rational;
5
6/// Per-packet flags.
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
8pub struct PacketFlags {
9 /// This packet begins a keyframe (random-access point).
10 pub keyframe: bool,
11 /// The last packet of its logical stream (Ogg: the final packet of the
12 /// end-of-stream page). Audio decoders trim this packet's output so the
13 /// stream ends at its [`Packet::end_position`], as FFmpeg does.
14 pub end_of_stream: bool,
15}
16
17/// A compressed packet belonging to a single stream.
18#[derive(Debug, Clone, Default)]
19pub struct Packet {
20 /// Index of the stream this packet belongs to within its container.
21 pub stream_index: usize,
22 /// Presentation timestamp, in the stream's `time_base` units. `None` if unset.
23 pub pts: Option<i64>,
24 /// Decode timestamp, in the stream's `time_base` units. `None` if unset.
25 pub dts: Option<i64>,
26 /// Duration of this packet, in `time_base` units (0 if unknown).
27 pub duration: i64,
28 /// Where the stream's decoded output ENDS once this packet is decoded, in
29 /// `time_base` units, when the container records it — Ogg's granule
30 /// position, which sits on the last packet completing each page (`None`
31 /// on the others, and in containers without one). Unlike `pts` it marks an
32 /// end, not a start: decoders count samples from it to trim end padding
33 /// off the [`end_of_stream`](PacketFlags::end_of_stream) packet.
34 pub end_position: Option<i64>,
35 /// Samples (per channel, at the stream's sample rate) to drop from the
36 /// END of this packet's decoded output; 0 = none. The container's record
37 /// of the encoder's end padding on a stream's last packet — Matroska's
38 /// `DiscardPadding`, FFmpeg's `AV_PKT_DATA_SKIP_SAMPLES` end field — for
39 /// containers whose timestamps are too coarse to carry it as an
40 /// [`end_position`](Self::end_position). As in FFmpeg, audio decoders drop
41 /// that many samples when it fits in what the packet decodes to and
42 /// ignore it otherwise.
43 pub discard_padding: u32,
44 /// The stream time base these timestamps are expressed in.
45 pub time_base: Rational,
46 /// The compressed payload.
47 pub data: Vec<u8>,
48 /// Packet flags (keyframe, ...).
49 pub flags: PacketFlags,
50}
51
52impl Packet {
53 /// Construct an empty packet for the given stream.
54 pub fn new(stream_index: usize) -> Packet {
55 Packet {
56 stream_index,
57 time_base: Rational::new(1, 1000),
58 ..Default::default()
59 }
60 }
61
62 /// Construct a packet wrapping an existing payload.
63 pub fn from_data(stream_index: usize, data: Vec<u8>) -> Packet {
64 Packet {
65 data,
66 ..Packet::new(stream_index)
67 }
68 }
69
70 pub fn is_keyframe(&self) -> bool {
71 self.flags.keyframe
72 }
73}