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