rsav/
packet.rs

1use std::io::Write;
2
3use ffmpeg_sys_next::{av_packet_make_writable, av_packet_ref};
4
5use crate::{container::{InputContainer, OutputContainer}, error::Error, ffi};
6
7pub struct Packet(ffi::AVPacket);
8
9unsafe impl Send for Packet {}
10unsafe impl Sync for Packet {}
11
12impl Packet {
13    #[inline]
14    pub fn empty() -> Self {
15        unsafe {
16            let mut pkt: ffi::AVPacket = std::mem::zeroed();
17            ffi::av_init_packet(&mut pkt);
18            Packet(pkt)
19        }
20    }
21
22    #[inline]
23    pub fn new(size: usize) -> Self {
24        unsafe {
25            let mut pkt: ffi::AVPacket = std::mem::zeroed();
26            ffi::av_init_packet(&mut pkt);
27            // TODO: handle error
28            ffi::av_new_packet(&mut pkt, size as _);
29            Packet(pkt)
30        }
31    }
32
33    #[inline]
34    pub fn from_slice(data: &[u8]) -> Self {
35        let mut pkt = Packet::new(data.len());
36        pkt.data_mut().unwrap().write_all(data).unwrap();
37        pkt
38    }
39
40    #[inline]
41    pub fn shrink(&mut self, size: usize) {
42        unsafe {
43            ffi::av_shrink_packet(&mut self.0, size as _);
44        }
45    }
46
47    #[inline]
48    pub fn grow(&mut self, size: usize) {
49        unsafe {
50            ffi::av_grow_packet(&mut self.0, size as _);
51        }
52    }
53
54    #[inline]
55    pub unsafe fn as_ptr(&self) -> *const ffi::AVPacket {
56        &self.0
57    }
58
59    #[inline]
60    pub unsafe fn as_mut_ptr(&mut self) -> *mut ffi::AVPacket {
61        &mut self.0
62    }
63}
64
65impl Packet {
66    #[inline]
67    pub fn stream_index(&self) -> u32 {
68        self.0.stream_index as _
69    }
70
71    #[inline]
72    pub fn set_stream_index(&mut self, index: u32) {
73        self.0.stream_index = index as _;
74    }
75
76    #[inline]
77    pub fn pts(&self) -> Option<i64> {
78        match self.0.pts {
79            ffi::AV_NOPTS_VALUE => None,
80            pts => Some(pts),
81        }
82    }
83
84    #[inline]
85    pub fn set_pts(&mut self, pts: Option<i64>) {
86        self.0.pts = pts.unwrap_or(ffi::AV_NOPTS_VALUE);
87    }
88
89    #[inline]
90    pub fn dts(&self) -> Option<i64> {
91        match self.0.dts {
92            ffi::AV_NOPTS_VALUE => None,
93            dts => Some(dts),
94        }
95    }
96
97    #[inline]
98    pub fn set_dts(&mut self, dts: Option<i64>) {
99        self.0.dts = dts.unwrap_or(ffi::AV_NOPTS_VALUE);
100    }
101
102    #[inline]
103    pub fn time_base(&self) -> crate::Rational {
104        self.0.time_base.into()
105    }
106
107    #[inline]
108    pub fn set_time_base<R: Into<crate::Rational>>(&mut self, time_base: R) {
109        self.0.time_base = time_base.into().into();
110    }
111
112    #[inline]
113    pub fn duration(&self) -> i64 {
114        self.0.duration
115    }
116
117    #[inline]
118    pub fn set_duration(&mut self, duration: i64) {
119        self.0.duration = duration;
120    }
121
122    #[inline]
123    pub fn pos(&self) -> i64 {
124        self.0.pos
125    }
126
127    #[inline]
128    pub fn set_pos(&mut self, pos: i64) {
129        self.0.pos = pos;
130    }
131
132    #[inline]
133    pub fn rescale_ts<S, D>(&mut self, source: Option<S>, dest: D)
134        where S: Into<crate::Rational>, D: Into<crate::Rational>
135    {
136        let source = match source {
137            Some(source) => source.into(),
138            None => self.time_base(),
139        };
140        let dest = dest.into();
141        unsafe {
142            ffi::av_packet_rescale_ts(&mut self.0, source.into(), dest.into());
143        }
144    }
145
146    #[inline]
147    pub fn size(&self) -> usize {
148        self.0.size as _
149    }
150
151    #[inline]
152    pub fn flags(&self) -> Flags {
153        Flags::from_bits_truncate(self.0.flags)
154    }
155
156    #[inline]
157    pub fn set_flags(&mut self, flags: Flags) {
158        self.0.flags = flags.bits();
159    }
160
161    #[inline]
162    pub fn is_key(&self) -> bool {
163        self.flags().contains(Flags::KEY)
164    }
165
166    #[inline]
167    pub fn is_corrupted(&self) -> bool {
168        self.flags().contains(Flags::CORRUPT)
169    }
170
171    #[inline]
172    pub fn is_discard(&self) -> bool {
173        self.flags().contains(Flags::DISCARD)
174    }
175
176    #[inline]
177    pub fn is_trusted(&self) -> bool {
178        self.flags().contains(Flags::TRUSTED)
179    }
180
181    #[inline]
182    pub fn is_disposable(&self) -> bool {
183        self.flags().contains(Flags::DISPOSABLE)
184    }
185
186    #[inline]
187    pub fn data(&self) -> Option<&[u8]> {
188        if self.0.data.is_null() {
189            None
190        } else {
191            Some(unsafe { std::slice::from_raw_parts(self.0.data, self.0.size as _) })
192        }
193    }
194
195    #[inline]
196    pub fn data_mut(&mut self) -> Option<&mut [u8]> {
197        if self.0.data.is_null() {
198            None
199        } else {
200            Some(unsafe { std::slice::from_raw_parts_mut(self.0.data, self.0.size as _) })
201        }
202    }
203}
204
205impl Packet {
206    #[inline]
207    pub fn read_from(&mut self, container: &mut InputContainer) -> Result<(), Error> {
208        unsafe {
209            match ffi::av_read_frame(container.as_mut_ptr(), self.as_mut_ptr()) {
210                0 => Ok(()),
211                e => Err(Error::from_ffmpeg_error_code(e)),
212            }
213        }
214    }
215
216    #[inline]
217    pub unsafe fn is_empty(&self) -> bool {
218        self.0.size == 0
219    }
220
221    #[inline]
222    pub fn write(&self, container: &mut OutputContainer) -> Result<bool, Error> {
223        unsafe {
224            if self.is_empty() {
225                return Err(Error::InvalidData);
226            }
227
228            match ffi::av_write_frame(container.as_mut_ptr(), self.as_ptr() as _) {
229                1 => Ok(true),
230                0 => Ok(false),
231                e => Err(Error::from_ffmpeg_error_code(e)),
232            }
233        }
234    }
235
236    #[inline]
237    pub fn write_interleaved(&self, container: &mut OutputContainer) -> Result<(), Error> {
238        unsafe {
239            if self.is_empty() {
240                return Err(Error::InvalidData);
241            }
242
243            match ffi::av_interleaved_write_frame(container.as_mut_ptr(), self.as_ptr() as _) {
244                0 => Ok(()),
245                e => Err(Error::from_ffmpeg_error_code(e)),
246            }
247        }
248    }
249}
250
251impl Clone for Packet {
252    #[inline]
253    fn clone(&self) -> Self {
254        let mut pkt = Packet::empty();
255        pkt.clone_from(self);
256        pkt
257    }
258
259    #[inline]
260    fn clone_from(&mut self, source: &Self) {
261        unsafe {
262            av_packet_ref(&mut self.0, &source.0);
263            av_packet_make_writable(&mut self.0);
264        }
265    }
266}
267
268impl Drop for Packet {
269    #[inline]
270    fn drop(&mut self) {
271        unsafe {
272            ffi::av_packet_unref(&mut self.0);
273        }
274    }
275}
276
277bitflags! {
278    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
279    pub struct Flags: i32 {
280        const KEY = ffi::AV_PKT_FLAG_KEY;
281        const CORRUPT = ffi::AV_PKT_FLAG_CORRUPT;
282        const DISCARD = ffi::AV_PKT_FLAG_DISCARD;
283        const TRUSTED = ffi::AV_PKT_FLAG_TRUSTED;
284        const DISPOSABLE = ffi::AV_PKT_FLAG_DISPOSABLE;
285    }
286}