ac_ffmpeg/
packet.rs

1//! AVPacket interface.
2//!
3//! A "packet" in the FFmpeg terminology is an encoded part of an elementary
4//! stream (i.e. audio or video stream).
5
6use std::{
7    ffi::CStr,
8    os::raw::{c_char, c_int, c_void},
9    ptr, slice,
10    time::Duration,
11};
12
13use crate::time::{TimeBase, Timestamp};
14
15extern "C" {
16    fn ffw_packet_alloc() -> *mut c_void;
17    fn ffw_packet_new(size: c_int) -> *mut c_void;
18    fn ffw_packet_clone(src: *const c_void) -> *mut c_void;
19    fn ffw_packet_free(packet: *mut c_void);
20    fn ffw_packet_get_size(packet: *const c_void) -> c_int;
21    fn ffw_packet_get_data(packet: *mut c_void) -> *mut c_void;
22    fn ffw_packet_get_pts(packet: *const c_void) -> i64;
23    fn ffw_packet_set_pts(packet: *mut c_void, pts: i64);
24    fn ffw_packet_get_dts(packet: *const c_void) -> i64;
25    fn ffw_packet_set_dts(packet: *mut c_void, pts: i64);
26    fn ffw_packet_get_duration(packet: *const c_void) -> i64;
27    fn ffw_packet_set_duration(packet: *mut c_void, duration: i64);
28    fn ffw_packet_is_key(packet: *const c_void) -> c_int;
29    fn ffw_packet_set_key(packet: *mut c_void, key: c_int);
30    fn ffw_packet_get_stream_index(packet: *const c_void) -> c_int;
31    fn ffw_packet_set_stream_index(packet: *mut c_void, index: c_int);
32    fn ffw_packet_is_writable(packet: *const c_void) -> c_int;
33    fn ffw_packet_make_writable(packet: *mut c_void) -> c_int;
34    fn ffw_packet_side_data_get_size(side_data: *const c_void) -> usize;
35    fn ffw_packet_side_data_get_data(side_data: *const c_void) -> *const u8;
36    fn ffw_packet_side_data_get_type(side_data: *const c_void) -> c_int;
37    fn ffw_packet_get_side_data_name(side_data_type: c_int) -> *const c_char;
38}
39
40/// Packet with mutable data.
41pub struct PacketMut {
42    ptr: *mut c_void,
43    time_base: TimeBase,
44}
45
46impl PacketMut {
47    /// Create a new packet of a given size. The time base of the packet will
48    /// be in microseconds.
49    pub fn new(size: usize) -> Self {
50        unsafe {
51            let ptr = if size == 0 {
52                ffw_packet_alloc()
53            } else {
54                ffw_packet_new(size as c_int)
55            };
56
57            if ptr.is_null() {
58                panic!("unable to allocate a packet");
59            }
60
61            Self {
62                ptr,
63                time_base: TimeBase::MICROSECONDS,
64            }
65        }
66    }
67
68    /// Get stream index.
69    pub fn stream_index(&self) -> usize {
70        unsafe { ffw_packet_get_stream_index(self.ptr) as _ }
71    }
72
73    /// Set stream index.
74    pub fn with_stream_index(self, index: usize) -> Self {
75        unsafe { ffw_packet_set_stream_index(self.ptr, index as _) }
76
77        self
78    }
79
80    /// Get packet time base.
81    #[inline]
82    pub fn time_base(&self) -> TimeBase {
83        self.time_base
84    }
85
86    /// Set packet time base. (This will rescale the current timestamps into a
87    /// given time base.)
88    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
89        let new_pts = self.pts().with_time_base(time_base);
90        let new_dts = self.dts().with_time_base(time_base);
91
92        unsafe {
93            ffw_packet_set_pts(self.ptr, new_pts.timestamp());
94            ffw_packet_set_dts(self.ptr, new_dts.timestamp());
95        }
96
97        self.time_base = time_base;
98
99        self
100    }
101
102    /// Get packet presentation timestamp.
103    pub fn pts(&self) -> Timestamp {
104        let pts = unsafe { ffw_packet_get_pts(self.ptr) };
105
106        Timestamp::new(pts, self.time_base)
107    }
108
109    /// Set packet presentation timestamp.
110    pub fn with_pts(self, pts: Timestamp) -> Self {
111        let pts = pts.with_time_base(self.time_base);
112
113        unsafe { ffw_packet_set_pts(self.ptr, pts.timestamp()) }
114
115        self
116    }
117
118    /// Set packet presentation timestamp without time base.
119    pub fn with_raw_pts(self, pts: i64) -> Self {
120        unsafe { ffw_packet_set_pts(self.ptr, pts) }
121
122        self
123    }
124
125    /// Get packet decoding timestamp.
126    pub fn dts(&self) -> Timestamp {
127        let dts = unsafe { ffw_packet_get_dts(self.ptr) };
128
129        Timestamp::new(dts, self.time_base)
130    }
131
132    /// Set packet decoding timestamp.
133    pub fn with_dts(self, dts: Timestamp) -> Self {
134        let dts = dts.with_time_base(self.time_base);
135
136        unsafe { ffw_packet_set_dts(self.ptr, dts.timestamp()) }
137
138        self
139    }
140
141    /// Set packet decoding timestamp without time base.
142    pub fn with_raw_dts(self, dts: i64) -> Self {
143        unsafe { ffw_packet_set_dts(self.ptr, dts) }
144
145        self
146    }
147
148    /// Get packet duration.
149    ///
150    /// The method returns `None` if the duration is lower or equal to zero.
151    pub fn duration(&self) -> Option<Duration> {
152        let duration = self.raw_duration();
153
154        if duration > 0 {
155            let z = Timestamp::new(0, self.time_base);
156            let d = Timestamp::new(duration, self.time_base);
157
158            Some(d - z)
159        } else {
160            None
161        }
162    }
163
164    /// Set packet duration.
165    pub fn with_duration(self, duration: Duration) -> Self {
166        let d = Timestamp::new(0, self.time_base) + duration;
167
168        unsafe { ffw_packet_set_duration(self.ptr, d.timestamp()) }
169
170        self
171    }
172
173    /// Get packet duration in time base units.
174    pub fn raw_duration(&self) -> i64 {
175        unsafe { ffw_packet_get_duration(self.ptr) }
176    }
177
178    /// Set packet duration in time base units.
179    pub fn with_raw_duration(self, duration: i64) -> Self {
180        unsafe { ffw_packet_set_duration(self.ptr, duration) }
181
182        self
183    }
184
185    /// Check if the key flag is set.
186    pub fn is_key(&self) -> bool {
187        unsafe { ffw_packet_is_key(self.ptr) != 0 }
188    }
189
190    /// Set or unset the key flag.
191    pub fn with_key_flag(self, key: bool) -> Self {
192        unsafe { ffw_packet_set_key(self.ptr, key as _) }
193
194        self
195    }
196
197    /// Get packet data.
198    pub fn data(&self) -> &[u8] {
199        unsafe {
200            let data = ffw_packet_get_data(self.ptr) as *const u8;
201            let size = ffw_packet_get_size(self.ptr) as usize;
202
203            if data.is_null() {
204                &[]
205            } else {
206                slice::from_raw_parts(data, size)
207            }
208        }
209    }
210
211    /// Get mutable reference to the packet data.
212    pub fn data_mut(&mut self) -> &mut [u8] {
213        unsafe {
214            let data = ffw_packet_get_data(self.ptr) as *mut u8;
215            let size = ffw_packet_get_size(self.ptr) as usize;
216
217            if data.is_null() {
218                &mut []
219            } else {
220                slice::from_raw_parts_mut(data, size)
221            }
222        }
223    }
224
225    /// Make the packet immutable.
226    pub fn freeze(mut self) -> Packet {
227        let ptr = self.ptr;
228
229        self.ptr = ptr::null_mut();
230
231        Packet {
232            ptr,
233            time_base: self.time_base,
234        }
235    }
236}
237
238impl Drop for PacketMut {
239    fn drop(&mut self) {
240        unsafe { ffw_packet_free(self.ptr) }
241    }
242}
243
244impl<T> From<T> for PacketMut
245where
246    T: AsRef<[u8]>,
247{
248    fn from(data: T) -> Self {
249        let data = data.as_ref();
250
251        let mut packet = Self::new(data.len());
252
253        packet.data_mut().copy_from_slice(data);
254
255        packet
256    }
257}
258
259unsafe impl Send for PacketMut {}
260unsafe impl Sync for PacketMut {}
261
262/// Packet with immutable data.
263pub struct Packet {
264    ptr: *mut c_void,
265    time_base: TimeBase,
266}
267
268impl Packet {
269    /// Create a new immutable packet from its raw representation.
270    pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
271        Packet { ptr, time_base }
272    }
273
274    /// Get stream index.
275    pub fn stream_index(&self) -> usize {
276        unsafe { ffw_packet_get_stream_index(self.ptr) as _ }
277    }
278
279    /// Set stream index.
280    pub fn with_stream_index(self, index: usize) -> Packet {
281        unsafe { ffw_packet_set_stream_index(self.ptr, index as _) }
282
283        self
284    }
285
286    /// Get packet time base.
287    #[inline]
288    pub fn time_base(&self) -> TimeBase {
289        self.time_base
290    }
291
292    /// Set packet time base. (This will rescale the current timestamps into a
293    /// given time base.)
294    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
295        let new_pts = self.pts().with_time_base(time_base);
296        let new_dts = self.dts().with_time_base(time_base);
297
298        unsafe {
299            ffw_packet_set_pts(self.ptr, new_pts.timestamp());
300            ffw_packet_set_dts(self.ptr, new_dts.timestamp());
301        }
302
303        self.time_base = time_base;
304
305        self
306    }
307
308    /// Get packet presentation timestamp.
309    pub fn pts(&self) -> Timestamp {
310        let pts = unsafe { ffw_packet_get_pts(self.ptr) };
311
312        Timestamp::new(pts, self.time_base)
313    }
314
315    /// Set packet presentation timestamp.
316    pub fn with_pts(self, pts: Timestamp) -> Self {
317        let pts = pts.with_time_base(self.time_base);
318
319        unsafe { ffw_packet_set_pts(self.ptr, pts.timestamp()) }
320
321        self
322    }
323
324    /// Set packet presentation timestamp without time base.
325    pub fn with_raw_pts(self, pts: i64) -> Self {
326        unsafe { ffw_packet_set_pts(self.ptr, pts) }
327
328        self
329    }
330
331    /// Get packet decoding timestamp.
332    pub fn dts(&self) -> Timestamp {
333        let dts = unsafe { ffw_packet_get_dts(self.ptr) };
334
335        Timestamp::new(dts, self.time_base)
336    }
337
338    /// Set packet decoding timestamp.
339    pub fn with_dts(self, dts: Timestamp) -> Self {
340        let dts = dts.with_time_base(self.time_base);
341
342        unsafe { ffw_packet_set_dts(self.ptr, dts.timestamp()) }
343
344        self
345    }
346
347    /// Set packet decoding timestamp without time base.
348    pub fn with_raw_dts(self, dts: i64) -> Self {
349        unsafe { ffw_packet_set_dts(self.ptr, dts) }
350
351        self
352    }
353
354    /// Get packet duration.
355    ///
356    /// The method returns `None` if the duration is lower or equal to zero.
357    pub fn duration(&self) -> Option<Duration> {
358        let duration = self.raw_duration();
359
360        if duration > 0 {
361            let z = Timestamp::new(0, self.time_base);
362            let d = Timestamp::new(duration, self.time_base);
363
364            Some(d - z)
365        } else {
366            None
367        }
368    }
369
370    /// Set packet duration.
371    pub fn with_duration(self, duration: Duration) -> Self {
372        let d = Timestamp::new(0, self.time_base) + duration;
373
374        unsafe { ffw_packet_set_duration(self.ptr, d.timestamp()) }
375
376        self
377    }
378
379    /// Get packet duration in time base units.
380    pub fn raw_duration(&self) -> i64 {
381        unsafe { ffw_packet_get_duration(self.ptr) }
382    }
383
384    /// Set packet duration in time base units.
385    pub fn with_raw_duration(self, duration: i64) -> Self {
386        unsafe { ffw_packet_set_duration(self.ptr, duration) }
387
388        self
389    }
390
391    /// Check if the key flag is set.
392    pub fn is_key(&self) -> bool {
393        unsafe { ffw_packet_is_key(self.ptr) != 0 }
394    }
395
396    /// Get raw pointer.
397    pub(crate) fn as_ptr(&self) -> *const c_void {
398        self.ptr
399    }
400
401    /// Get mutable raw pointer. Please note that even though it is required
402    /// in some cases to pass a mut pointer to an immutable packet, it is not
403    /// allowed to modify packet data in such cases.
404    pub(crate) fn as_mut_ptr(&mut self) -> *mut c_void {
405        self.ptr
406    }
407
408    /// Get packet data.
409    pub fn data(&self) -> &[u8] {
410        unsafe {
411            let data = ffw_packet_get_data(self.ptr) as *const u8;
412            let size = ffw_packet_get_size(self.ptr) as usize;
413
414            if data.is_null() {
415                &[]
416            } else {
417                slice::from_raw_parts(data, size)
418            }
419        }
420    }
421
422    /// Try to make this packet mutable.
423    ///
424    /// The method returns `PacketMut` if the packet can be made mutable
425    /// without copying the data, otherwise it returns `Packet`.
426    pub fn try_into_mut(self) -> Result<PacketMut, Self> {
427        let res = unsafe { ffw_packet_is_writable(self.ptr) };
428
429        if res == 0 {
430            Err(self)
431        } else {
432            Ok(self.into_mut())
433        }
434    }
435
436    /// Make this packet mutable.
437    ///
438    /// If there are no other references to the packet data, the mutable packet
439    /// will be created without copying the data.
440    pub fn into_mut(mut self) -> PacketMut {
441        let res = unsafe { ffw_packet_make_writable(self.ptr) };
442
443        if res < 0 {
444            panic!("unable to make the packet mutable");
445        }
446
447        let ptr = self.ptr;
448
449        self.ptr = ptr::null_mut();
450
451        PacketMut {
452            ptr,
453            time_base: self.time_base,
454        }
455    }
456}
457
458impl Clone for Packet {
459    fn clone(&self) -> Packet {
460        let ptr = unsafe { ffw_packet_clone(self.ptr) };
461
462        if ptr.is_null() {
463            panic!("unable to clone a packet");
464        }
465
466        Packet {
467            ptr,
468            time_base: self.time_base,
469        }
470    }
471}
472
473impl Drop for Packet {
474    fn drop(&mut self) {
475        unsafe { ffw_packet_free(self.ptr) }
476    }
477}
478
479unsafe impl Send for Packet {}
480unsafe impl Sync for Packet {}
481
482/// Reference to the packet side data.
483pub struct SideDataRef(());
484
485impl SideDataRef {
486    /// Create a packet side data from its raw representation.
487    #[cfg(any(stream_side_data, codec_params_side_data))]
488    pub(crate) unsafe fn from_raw_ptr<'a>(ptr: *const c_void) -> &'a Self {
489        unsafe { &*(ptr as *const Self) }
490    }
491
492    /// Get raw pointer.
493    fn as_ptr(&self) -> *const c_void {
494        self as *const Self as _
495    }
496
497    /// Get data.
498    pub fn data(&self) -> &[u8] {
499        unsafe {
500            let data = ffw_packet_side_data_get_data(self.as_ptr());
501            let len = ffw_packet_side_data_get_size(self.as_ptr());
502
503            std::slice::from_raw_parts(data, len)
504        }
505    }
506
507    /// Get data type.
508    pub fn data_type(&self) -> SideDataType {
509        let data_type = unsafe { ffw_packet_side_data_get_type(self.as_ptr()) };
510
511        SideDataType::from_raw(data_type)
512    }
513}
514
515/// Packet side data type.
516pub struct SideDataType(c_int);
517
518impl SideDataType {
519    /// Create a packet side data type value from a given raw representation.
520    pub(crate) fn from_raw(v: c_int) -> Self {
521        Self(v)
522    }
523
524    /// Get the raw value.
525    pub(crate) fn into_raw(self) -> c_int {
526        self.0
527    }
528
529    /// Get name of the packet side data type.
530    pub fn name(self) -> &'static str {
531        unsafe {
532            let ptr = ffw_packet_get_side_data_name(self.into_raw());
533
534            if ptr.is_null() {
535                panic!("invalid packet side data type");
536            }
537
538            let name = CStr::from_ptr(ptr as _);
539
540            name.to_str().unwrap()
541        }
542    }
543}