1use std::marker::PhantomData;
2
3use crate::error::{FfmpegError, FfmpegErrorCode};
4use crate::ffi::*;
5use crate::rational::Rational;
6use crate::smart_object::SmartPtr;
7use crate::utils::{check_i64, or_nopts};
8use crate::{AVPktFlags, AVRounding};
9
10pub struct Packets<'a> {
13 context: *mut AVFormatContext,
14 _marker: PhantomData<&'a mut AVFormatContext>,
15}
16
17impl std::fmt::Debug for Packets<'_> {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 f.debug_struct("Packets").field("context", &self.context).finish()
20 }
21}
22
23unsafe impl Send for Packets<'_> {}
25
26impl Packets<'_> {
27 pub const unsafe fn new(context: *mut AVFormatContext) -> Self {
33 Self {
34 context,
35 _marker: PhantomData,
36 }
37 }
38
39 pub fn receive(&mut self) -> Result<Option<Packet>, FfmpegError> {
41 let mut packet = Packet::new()?;
42
43 match FfmpegErrorCode(unsafe { av_read_frame(self.context, packet.as_mut_ptr()) }) {
45 code if code.is_success() => Ok(Some(packet)),
46 FfmpegErrorCode::Eof => Ok(None),
47 code => Err(FfmpegError::Code(code)),
48 }
49 }
50}
51
52impl Iterator for Packets<'_> {
53 type Item = Result<Packet, FfmpegError>;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 self.receive().transpose()
57 }
58}
59
60pub struct Packet(SmartPtr<AVPacket>);
62
63unsafe impl Send for Packet {}
65
66impl std::fmt::Debug for Packet {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct("Packet")
69 .field("stream_index", &self.stream_index())
70 .field("pts", &self.pts())
71 .field("dts", &self.dts())
72 .field("duration", &self.duration())
73 .field("pos", &self.pos())
74 .field("is_key", &self.is_key())
75 .field("is_corrupt", &self.is_corrupt())
76 .field("is_discard", &self.is_discard())
77 .field("is_trusted", &self.is_trusted())
78 .field("is_disposable", &self.is_disposable())
79 .finish()
80 }
81}
82
83impl Clone for Packet {
84 fn clone(&self) -> Self {
85 let clone = unsafe { av_packet_clone(self.0.as_ptr()) };
87
88 unsafe { Self::wrap(clone).expect("failed to clone packet") }
90 }
91}
92
93impl Packet {
94 pub fn new() -> Result<Self, FfmpegError> {
96 let packet = unsafe { av_packet_alloc() };
98
99 unsafe { Self::wrap(packet) }.ok_or(FfmpegError::Alloc)
101 }
102
103 unsafe fn wrap(ptr: *mut AVPacket) -> Option<Self> {
108 SmartPtr::wrap_non_null(ptr, |ptr| av_packet_free(ptr)).map(Self)
109 }
110
111 pub const fn as_ptr(&self) -> *const AVPacket {
113 self.0.as_ptr()
114 }
115
116 pub const fn as_mut_ptr(&mut self) -> *mut AVPacket {
118 self.0.as_mut_ptr()
119 }
120
121 pub const fn stream_index(&self) -> i32 {
123 self.0.as_deref_except().stream_index
124 }
125
126 pub const fn set_stream_index(&mut self, stream_index: i32) {
128 self.0.as_deref_mut_except().stream_index = stream_index as _;
129 }
130
131 pub const fn pts(&self) -> Option<i64> {
133 check_i64(self.0.as_deref_except().pts)
134 }
135
136 pub const fn set_pts(&mut self, pts: Option<i64>) {
138 self.0.as_deref_mut_except().pts = or_nopts(pts);
139 }
140
141 pub const fn dts(&self) -> Option<i64> {
143 check_i64(self.0.as_deref_except().dts)
144 }
145
146 pub const fn set_dts(&mut self, dts: Option<i64>) {
148 self.0.as_deref_mut_except().dts = or_nopts(dts);
149 }
150
151 pub const fn duration(&self) -> Option<i64> {
153 check_i64(self.0.as_deref_except().duration)
154 }
155
156 pub const fn set_duration(&mut self, duration: Option<i64>) {
158 self.0.as_deref_mut_except().duration = or_nopts(duration);
159 }
160
161 pub fn convert_timebase(&mut self, from: impl Into<Rational>, to: impl Into<Rational>) {
163 let from = from.into();
164 let to = to.into();
165
166 self.set_pts(self.pts().map(|pts| {
168 unsafe { av_rescale_q_rnd(pts, from.into(), to.into(), AVRounding::NearestAwayFromZero.0 as u32) }
170 }));
171
172 self.set_dts(self.dts().map(|dts| {
174 unsafe { av_rescale_q_rnd(dts, from.into(), to.into(), AVRounding::NearestAwayFromZero.0 as u32) }
176 }));
177
178 self.set_duration(
179 self.duration()
180 .map(|duration| unsafe { av_rescale_q(duration, from.into(), to.into()) }),
182 );
183 }
184
185 pub const fn pos(&self) -> Option<i64> {
187 check_i64(self.0.as_deref_except().pos)
188 }
189
190 pub const fn set_pos(&mut self, pos: Option<i64>) {
192 self.0.as_deref_mut_except().pos = or_nopts(pos);
193 }
194
195 pub const fn data(&self) -> &[u8] {
197 if self.0.as_deref_except().size <= 0 {
198 return &[];
199 }
200
201 unsafe { std::slice::from_raw_parts(self.0.as_deref_except().data, self.0.as_deref_except().size as usize) }
203 }
204
205 pub fn is_key(&self) -> bool {
207 self.flags() & AVPktFlags::Key != 0
208 }
209
210 pub fn is_corrupt(&self) -> bool {
212 self.flags() & AVPktFlags::Corrupt != 0
213 }
214
215 pub fn is_discard(&self) -> bool {
217 self.flags() & AVPktFlags::Discard != 0
218 }
219
220 pub fn is_trusted(&self) -> bool {
222 self.flags() & AVPktFlags::Trusted != 0
223 }
224
225 pub fn is_disposable(&self) -> bool {
227 self.flags() & AVPktFlags::Disposable != 0
228 }
229
230 pub const fn flags(&self) -> AVPktFlags {
232 AVPktFlags(self.0.as_deref_except().flags)
233 }
234}
235
236#[cfg(test)]
237#[cfg_attr(all(test, coverage_nightly), coverage(off))]
238mod tests {
239 use insta::assert_debug_snapshot;
240
241 use crate::ffi::AVRational;
242 use crate::packet::Packet;
243
244 #[test]
245 fn test_packet_clone_snapshot() {
246 let mut original_packet = Packet::new().expect("Failed to create original Packet");
247 original_packet.set_stream_index(1);
248 original_packet.set_pts(Some(12345));
249 original_packet.set_dts(Some(54321));
250 original_packet.set_duration(Some(1000));
251 original_packet.set_pos(Some(2000));
252
253 let cloned_packet = original_packet.clone();
254
255 assert_debug_snapshot!(cloned_packet, @r"
256 Packet {
257 stream_index: 1,
258 pts: Some(
259 12345,
260 ),
261 dts: Some(
262 54321,
263 ),
264 duration: Some(
265 1000,
266 ),
267 pos: Some(
268 2000,
269 ),
270 is_key: false,
271 is_corrupt: false,
272 is_discard: false,
273 is_trusted: false,
274 is_disposable: false,
275 }
276 ");
277
278 original_packet.set_pts(Some(99999));
280 assert_ne!(
281 cloned_packet.pts(),
282 original_packet.pts(),
283 "Expected cloned packet PTS to remain unchanged after modifying the original"
284 );
285
286 assert_debug_snapshot!(original_packet, @r"
287 Packet {
288 stream_index: 1,
289 pts: Some(
290 99999,
291 ),
292 dts: Some(
293 54321,
294 ),
295 duration: Some(
296 1000,
297 ),
298 pos: Some(
299 2000,
300 ),
301 is_key: false,
302 is_corrupt: false,
303 is_discard: false,
304 is_trusted: false,
305 is_disposable: false,
306 }
307 ");
308 }
309
310 #[test]
311 fn test_packet_as_ptr() {
312 let packet = Packet::new().expect("Failed to create Packet");
313 let raw_ptr = packet.as_ptr();
314
315 assert!(!raw_ptr.is_null(), "Expected a non-null pointer from Packet::as_ptr");
316 unsafe {
318 assert_eq!(
319 (*raw_ptr).stream_index,
320 0,
321 "Expected the default stream_index to be 0 for a new Packet"
322 );
323 }
324 }
325
326 #[test]
327 fn test_packet_rescale_timebase() {
328 let mut packet = Packet::new().expect("Failed to create Packet");
329 packet.set_pts(Some(1000));
330 packet.set_dts(Some(900));
331 packet.set_duration(Some(100));
332 let from_time_base = AVRational { num: 1, den: 1000 };
333 let to_time_base = AVRational { num: 1, den: 48000 };
334
335 packet.convert_timebase(from_time_base, to_time_base);
336 assert_debug_snapshot!(packet, @r"
337 Packet {
338 stream_index: 0,
339 pts: Some(
340 48000,
341 ),
342 dts: Some(
343 43200,
344 ),
345 duration: Some(
346 4800,
347 ),
348 pos: Some(
349 -1,
350 ),
351 is_key: false,
352 is_corrupt: false,
353 is_discard: false,
354 is_trusted: false,
355 is_disposable: false,
356 }
357 ");
358 }
359
360 #[test]
361 fn test_packet_data_empty() {
362 let mut packet = Packet::new().expect("Failed to create Packet");
363 unsafe {
365 let av_packet = packet.as_mut_ptr().as_mut().unwrap();
366 av_packet.size = 0;
367 }
368
369 let data = packet.data();
370
371 assert!(
372 data.is_empty(),
373 "Expected the data slice to be empty when packet size is zero"
374 );
375 }
376}