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 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}