Skip to main content

ffmpeg_next/codec/packet/
packet.rs

1use std::marker::PhantomData;
2use std::mem;
3use std::slice;
4
5use super::{Borrow, Flags, Mut, Ref, SideData};
6use ffi::*;
7use libc::c_int;
8use {format, Error, Rational};
9
10pub struct Packet(AVPacket);
11
12unsafe impl Send for Packet {}
13unsafe impl Sync for Packet {}
14
15impl Packet {
16    #[inline(always)]
17    pub unsafe fn is_empty(&self) -> bool {
18        self.0.size == 0
19    }
20}
21
22impl Packet {
23    #[inline]
24    pub fn empty() -> Self {
25        unsafe {
26            let mut pkt: AVPacket = mem::zeroed();
27
28            av_init_packet(&mut pkt);
29
30            Packet(pkt)
31        }
32    }
33
34    #[inline]
35    pub fn new(size: usize) -> Self {
36        unsafe {
37            let mut pkt: AVPacket = mem::zeroed();
38
39            av_init_packet(&mut pkt);
40            av_new_packet(&mut pkt, size as c_int);
41
42            Packet(pkt)
43        }
44    }
45
46    #[inline]
47    pub fn copy(data: &[u8]) -> Self {
48        use std::io::Write;
49
50        let mut packet = Packet::new(data.len());
51        packet.data_mut().unwrap().write_all(data).unwrap();
52
53        packet
54    }
55
56    #[inline]
57    pub fn borrow(data: &[u8]) -> Borrow<'_> {
58        Borrow::new(data)
59    }
60
61    #[inline]
62    pub fn shrink(&mut self, size: usize) {
63        unsafe {
64            av_shrink_packet(&mut self.0, size as c_int);
65        }
66    }
67
68    #[inline]
69    pub fn grow(&mut self, size: usize) {
70        unsafe {
71            av_grow_packet(&mut self.0, size as c_int);
72        }
73    }
74
75    #[inline]
76    pub fn rescale_ts<S, D>(&mut self, source: S, destination: D)
77    where
78        S: Into<Rational>,
79        D: Into<Rational>,
80    {
81        unsafe {
82            av_packet_rescale_ts(
83                self.as_mut_ptr(),
84                source.into().into(),
85                destination.into().into(),
86            );
87        }
88    }
89
90    #[inline]
91    pub fn flags(&self) -> Flags {
92        Flags::from_bits_truncate(self.0.flags)
93    }
94
95    #[inline]
96    pub fn set_flags(&mut self, value: Flags) {
97        self.0.flags = value.bits();
98    }
99
100    #[inline]
101    pub fn is_key(&self) -> bool {
102        self.flags().contains(Flags::KEY)
103    }
104
105    #[inline]
106    pub fn is_corrupt(&self) -> bool {
107        self.flags().contains(Flags::CORRUPT)
108    }
109
110    #[inline]
111    pub fn stream(&self) -> usize {
112        self.0.stream_index as usize
113    }
114
115    #[inline]
116    pub fn set_stream(&mut self, index: usize) {
117        self.0.stream_index = index as c_int;
118    }
119
120    #[inline]
121    pub fn pts(&self) -> Option<i64> {
122        match self.0.pts {
123            AV_NOPTS_VALUE => None,
124            pts => Some(pts),
125        }
126    }
127
128    #[inline]
129    pub fn set_pts(&mut self, value: Option<i64>) {
130        self.0.pts = value.unwrap_or(AV_NOPTS_VALUE);
131    }
132
133    #[inline]
134    pub fn dts(&self) -> Option<i64> {
135        match self.0.dts {
136            AV_NOPTS_VALUE => None,
137            dts => Some(dts),
138        }
139    }
140
141    #[inline]
142    pub fn set_dts(&mut self, value: Option<i64>) {
143        self.0.dts = value.unwrap_or(AV_NOPTS_VALUE);
144    }
145
146    #[inline]
147    #[cfg(feature = "ffmpeg_5_0")]
148    pub fn time_base(&self) -> Rational {
149        self.0.time_base.into()
150    }
151
152    #[inline]
153    #[cfg(feature = "ffmpeg_5_0")]
154    pub fn set_time_base(&mut self, value: Rational) {
155        self.0.time_base = value.into();
156    }
157
158    #[inline]
159    pub fn size(&self) -> usize {
160        self.0.size as usize
161    }
162
163    #[inline]
164    pub fn duration(&self) -> i64 {
165        self.0.duration
166    }
167
168    #[inline]
169    pub fn set_duration(&mut self, value: i64) {
170        self.0.duration = value;
171    }
172
173    #[inline]
174    pub fn position(&self) -> isize {
175        self.0.pos as isize
176    }
177
178    #[inline]
179    pub fn set_position(&mut self, value: isize) {
180        self.0.pos = value as i64
181    }
182
183    #[inline]
184    #[cfg(not(feature = "ffmpeg_5_0"))]
185    pub fn convergence(&self) -> isize {
186        self.0.convergence_duration as isize
187    }
188
189    #[inline]
190    pub fn side_data(&self) -> SideDataIter<'_> {
191        SideDataIter::new(&self.0)
192    }
193
194    #[inline]
195    pub fn data(&self) -> Option<&[u8]> {
196        unsafe {
197            if self.0.data.is_null() {
198                None
199            } else {
200                Some(slice::from_raw_parts(self.0.data, self.0.size as usize))
201            }
202        }
203    }
204
205    #[inline]
206    pub fn data_mut(&mut self) -> Option<&mut [u8]> {
207        unsafe {
208            if self.0.data.is_null() {
209                None
210            } else {
211                Some(slice::from_raw_parts_mut(self.0.data, self.0.size as usize))
212            }
213        }
214    }
215
216    #[inline]
217    pub fn read(&mut self, format: &mut format::context::Input) -> Result<(), Error> {
218        unsafe {
219            match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) {
220                0 => Ok(()),
221                e => Err(Error::from(e)),
222            }
223        }
224    }
225
226    #[inline]
227    pub fn write(&self, format: &mut format::context::Output) -> Result<bool, Error> {
228        unsafe {
229            if self.is_empty() {
230                return Err(Error::InvalidData);
231            }
232
233            match av_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) {
234                1 => Ok(true),
235                0 => Ok(false),
236                e => Err(Error::from(e)),
237            }
238        }
239    }
240
241    #[inline]
242    pub fn write_interleaved(&self, format: &mut format::context::Output) -> Result<(), Error> {
243        unsafe {
244            if self.is_empty() {
245                return Err(Error::InvalidData);
246            }
247
248            match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) {
249                0 => Ok(()),
250                e => Err(Error::from(e)),
251            }
252        }
253    }
254}
255
256impl Ref for Packet {
257    fn as_ptr(&self) -> *const AVPacket {
258        &self.0
259    }
260}
261
262impl Mut for Packet {
263    fn as_mut_ptr(&mut self) -> *mut AVPacket {
264        &mut self.0
265    }
266}
267
268impl Clone for Packet {
269    #[inline]
270    fn clone(&self) -> Self {
271        let mut pkt = Packet::empty();
272        pkt.clone_from(self);
273
274        pkt
275    }
276
277    #[inline]
278    fn clone_from(&mut self, source: &Self) {
279        #[cfg(feature = "ffmpeg_4_0")]
280        unsafe {
281            av_packet_ref(&mut self.0, &source.0);
282            av_packet_make_writable(&mut self.0);
283        }
284        #[cfg(not(feature = "ffmpeg_4_0"))]
285        unsafe {
286            av_copy_packet(&mut self.0, &source.0);
287        }
288    }
289}
290
291impl Drop for Packet {
292    fn drop(&mut self) {
293        unsafe {
294            av_packet_unref(&mut self.0);
295        }
296    }
297}
298
299pub struct SideDataIter<'a> {
300    ptr: *const AVPacket,
301    cur: c_int,
302
303    _marker: PhantomData<&'a Packet>,
304}
305
306impl<'a> SideDataIter<'a> {
307    pub fn new(ptr: *const AVPacket) -> Self {
308        SideDataIter {
309            ptr,
310            cur: 0,
311            _marker: PhantomData,
312        }
313    }
314}
315
316impl<'a> Iterator for SideDataIter<'a> {
317    type Item = SideData<'a>;
318
319    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
320        unsafe {
321            if self.cur >= (*self.ptr).side_data_elems {
322                None
323            } else {
324                self.cur += 1;
325                Some(SideData::wrap(
326                    (*self.ptr).side_data.offset((self.cur - 1) as isize),
327                ))
328            }
329        }
330    }
331
332    fn size_hint(&self) -> (usize, Option<usize>) {
333        unsafe {
334            let length = (*self.ptr).side_data_elems as usize;
335
336            (length - self.cur as usize, Some(length - self.cur as usize))
337        }
338    }
339}
340
341impl<'a> ExactSizeIterator for SideDataIter<'a> {}