oximedia_container/
packet.rs1use bitflags::bitflags;
4use bytes::Bytes;
5use oximedia_core::Timestamp;
6
7bitflags! {
8 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13 pub struct PacketFlags: u32 {
14 const KEYFRAME = 0x0001;
19
20 const CORRUPT = 0x0002;
25
26 const DISCARD = 0x0004;
31 }
32}
33
34impl Default for PacketFlags {
35 fn default() -> Self {
36 Self::empty()
37 }
38}
39
40#[derive(Clone, Debug)]
64pub struct Packet {
65 pub stream_index: usize,
67
68 pub data: Bytes,
70
71 pub timestamp: Timestamp,
73
74 pub flags: PacketFlags,
76}
77
78impl Packet {
79 #[must_use]
88 pub const fn new(
89 stream_index: usize,
90 data: Bytes,
91 timestamp: Timestamp,
92 flags: PacketFlags,
93 ) -> Self {
94 Self {
95 stream_index,
96 data,
97 timestamp,
98 flags,
99 }
100 }
101
102 #[must_use]
107 pub const fn is_keyframe(&self) -> bool {
108 self.flags.contains(PacketFlags::KEYFRAME)
109 }
110
111 #[must_use]
113 pub const fn is_corrupt(&self) -> bool {
114 self.flags.contains(PacketFlags::CORRUPT)
115 }
116
117 #[must_use]
119 pub const fn should_discard(&self) -> bool {
120 self.flags.contains(PacketFlags::DISCARD)
121 }
122
123 #[must_use]
125 pub fn size(&self) -> usize {
126 self.data.len()
127 }
128
129 #[must_use]
131 pub fn is_empty(&self) -> bool {
132 self.data.is_empty()
133 }
134
135 #[must_use]
137 pub const fn pts(&self) -> i64 {
138 self.timestamp.pts
139 }
140
141 #[must_use]
143 pub const fn dts(&self) -> Option<i64> {
144 self.timestamp.dts
145 }
146
147 #[must_use]
149 pub const fn duration(&self) -> Option<i64> {
150 self.timestamp.duration
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use oximedia_core::Rational;
158
159 #[test]
160 fn test_packet_new() {
161 let data = Bytes::from_static(&[1, 2, 3, 4, 5]);
162 let timestamp = Timestamp::new(1000, Rational::new(1, 1000));
163 let packet = Packet::new(0, data, timestamp, PacketFlags::KEYFRAME);
164
165 assert_eq!(packet.stream_index, 0);
166 assert_eq!(packet.size(), 5);
167 assert!(packet.is_keyframe());
168 assert!(!packet.is_corrupt());
169 }
170
171 #[test]
172 fn test_packet_flags() {
173 let data = Bytes::new();
174 let timestamp = Timestamp::new(0, Rational::new(1, 1000));
175
176 let keyframe = Packet::new(0, data.clone(), timestamp, PacketFlags::KEYFRAME);
177 assert!(keyframe.is_keyframe());
178 assert!(!keyframe.is_corrupt());
179
180 let corrupt = Packet::new(
181 0,
182 data.clone(),
183 timestamp,
184 PacketFlags::CORRUPT | PacketFlags::KEYFRAME,
185 );
186 assert!(corrupt.is_keyframe());
187 assert!(corrupt.is_corrupt());
188
189 let discard = Packet::new(0, data, timestamp, PacketFlags::DISCARD);
190 assert!(discard.should_discard());
191 }
192
193 #[test]
194 fn test_packet_timestamps() {
195 let data = Bytes::new();
196 let mut timestamp = Timestamp::new(1000, Rational::new(1, 48000));
197 timestamp.dts = Some(999);
198 timestamp.duration = Some(1024);
199
200 let packet = Packet::new(0, data, timestamp, PacketFlags::empty());
201
202 assert_eq!(packet.pts(), 1000);
203 assert_eq!(packet.dts(), Some(999));
204 assert_eq!(packet.duration(), Some(1024));
205 }
206
207 #[test]
208 fn test_packet_is_empty() {
209 let timestamp = Timestamp::new(0, Rational::new(1, 1000));
210
211 let empty = Packet::new(0, Bytes::new(), timestamp, PacketFlags::empty());
212 assert!(empty.is_empty());
213 assert_eq!(empty.size(), 0);
214
215 let non_empty = Packet::new(0, Bytes::from_static(&[1]), timestamp, PacketFlags::empty());
216 assert!(!non_empty.is_empty());
217 assert_eq!(non_empty.size(), 1);
218 }
219}