playa_ffmpeg/util/frame/
mod.rs1pub mod side_data;
2pub use self::side_data::SideData;
3
4pub mod video;
5pub use self::video::Video;
6
7pub mod audio;
8pub use self::audio::Audio;
9
10pub mod flag;
11pub use self::flag::Flags;
12
13use crate::{Dictionary, DictionaryRef, ffi::*};
14
15#[derive(PartialEq, Eq, Copy, Clone, Debug)]
16pub struct Packet {
17 pub duration: i64,
18 #[cfg(not(feature = "ffmpeg_8_0"))]
19 pub position: i64,
20 #[cfg(not(feature = "ffmpeg_8_0"))]
21 pub size: usize,
22
23 #[cfg(not(feature = "ffmpeg_5_0"))]
24 pub pts: i64,
25 pub dts: i64,
26}
27
28#[derive(PartialEq, Eq)]
29pub struct Frame {
30 ptr: *mut AVFrame,
31
32 _own: bool,
33}
34
35unsafe impl Send for Frame {}
36unsafe impl Sync for Frame {}
37
38impl Frame {
39 #[inline(always)]
40 pub unsafe fn wrap(ptr: *mut AVFrame) -> Self {
41 Frame { ptr, _own: false }
42 }
43
44 #[inline(always)]
45 pub unsafe fn empty() -> Self {
46 Frame { ptr: unsafe { av_frame_alloc() }, _own: true }
47 }
48
49 #[inline(always)]
50 pub unsafe fn as_ptr(&self) -> *const AVFrame {
51 self.ptr as *const _
52 }
53
54 #[inline(always)]
55 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrame {
56 self.ptr
57 }
58
59 #[inline(always)]
60 pub unsafe fn is_empty(&self) -> bool {
61 unsafe { (*self.as_ptr()).data[0].is_null() }
62 }
63}
64
65impl Frame {
66 #[inline]
67 pub fn is_key(&self) -> bool {
68 #[cfg(not(feature = "ffmpeg_8_0"))]
69 unsafe {
70 (*self.as_ptr()).key_frame == 1
71 }
72 #[cfg(feature = "ffmpeg_8_0")]
73 unsafe {
74 ((*self.as_ptr()).flags & AV_FRAME_FLAG_KEY) != 0
75 }
76 }
77
78 #[inline]
79 pub fn is_corrupt(&self) -> bool {
80 self.flags().contains(Flags::CORRUPT)
81 }
82
83 #[inline]
84 pub fn packet(&self) -> Packet {
85 unsafe {
86 Packet {
87 #[cfg(not(feature = "ffmpeg_7_0"))]
88 duration: (*self.as_ptr()).pkt_duration,
89 #[cfg(feature = "ffmpeg_7_0")]
90 duration: (*self.as_ptr()).duration,
91
92 #[cfg(not(feature = "ffmpeg_8_0"))]
93 position: (*self.as_ptr()).pkt_pos,
94 #[cfg(not(feature = "ffmpeg_8_0"))]
95 size: (*self.as_ptr()).pkt_size as usize,
96
97 #[cfg(not(feature = "ffmpeg_5_0"))]
98 pts: (*self.as_ptr()).pkt_pts,
99 dts: (*self.as_ptr()).pkt_dts,
100 }
101 }
102 }
103
104 #[inline]
105 pub fn pts(&self) -> Option<i64> {
106 unsafe {
107 match (*self.as_ptr()).pts {
108 AV_NOPTS_VALUE => None,
109 pts => Some(pts),
110 }
111 }
112 }
113
114 #[inline]
115 pub fn set_pts(&mut self, value: Option<i64>) {
116 unsafe {
117 (*self.as_mut_ptr()).pts = value.unwrap_or(AV_NOPTS_VALUE);
118 }
119 }
120
121 #[inline]
122 pub fn timestamp(&self) -> Option<i64> {
123 unsafe {
124 match (*self.as_ptr()).best_effort_timestamp {
125 AV_NOPTS_VALUE => None,
126 t => Some(t),
127 }
128 }
129 }
130
131 #[inline]
132 pub fn quality(&self) -> usize {
133 unsafe { (*self.as_ptr()).quality as usize }
134 }
135
136 #[inline]
137 pub fn flags(&self) -> Flags {
138 unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
139 }
140
141 #[inline]
142 pub fn metadata(&self) -> DictionaryRef<'_> {
143 unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
144 }
145
146 #[inline]
147 pub fn set_metadata(&mut self, value: Dictionary) {
148 unsafe { (*self.as_mut_ptr()).metadata = value.disown() }
149 }
150
151 #[inline]
152 pub fn side_data(&self, kind: side_data::Type) -> Option<SideData<'_>> {
153 unsafe {
154 let ptr = av_frame_get_side_data(self.as_ptr(), kind.into());
155
156 if ptr.is_null() { None } else { Some(SideData::wrap(ptr)) }
157 }
158 }
159
160 #[inline]
161 pub fn new_side_data(&mut self, kind: side_data::Type, size: usize) -> Option<SideData<'_>> {
162 unsafe {
163 let ptr = av_frame_new_side_data(self.as_mut_ptr(), kind.into(), size as _);
164
165 if ptr.is_null() { None } else { Some(SideData::wrap(ptr)) }
166 }
167 }
168
169 #[inline]
170 pub fn remove_side_data(&mut self, kind: side_data::Type) {
171 unsafe {
172 av_frame_remove_side_data(self.as_mut_ptr(), kind.into());
173 }
174 }
175}
176
177impl Drop for Frame {
178 #[inline]
179 fn drop(&mut self) {
180 unsafe {
181 av_frame_free(&mut self.as_mut_ptr());
182 }
183 }
184}