gstreamer_video/
video_codec_frame.rs
1use std::{fmt, marker::PhantomData, mem};
4
5use glib::translate::*;
6
7use crate::{ffi, utils::HasStreamLock, VideoCodecFrameFlags};
8
9pub struct VideoCodecFrame<'a> {
12 frame: *mut ffi::GstVideoCodecFrame,
13 element: &'a dyn HasStreamLock,
16}
17
18#[doc(hidden)]
19impl<'a> ::glib::translate::ToGlibPtr<'a, *mut ffi::GstVideoCodecFrame> for VideoCodecFrame<'a> {
20 type Storage = PhantomData<&'a Self>;
21
22 #[inline]
23 fn to_glib_none(&'a self) -> ::glib::translate::Stash<'a, *mut ffi::GstVideoCodecFrame, Self> {
24 Stash(self.frame, PhantomData)
25 }
26
27 #[inline]
28 fn to_glib_full(&self) -> *mut ffi::GstVideoCodecFrame {
29 unsafe { ffi::gst_video_codec_frame_ref(self.frame) }
30 }
31}
32
33impl fmt::Debug for VideoCodecFrame<'_> {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 let mut b = f.debug_struct("VideoCodecFrame");
36
37 b.field("flags", &self.flags())
38 .field("system_frame_number", &self.system_frame_number())
39 .field("decode_frame_number", &self.decode_frame_number())
40 .field(
41 "presentation_frame_number",
42 &self.presentation_frame_number(),
43 )
44 .field("dts", &self.dts())
45 .field("pts", &self.pts())
46 .field("duration", &self.duration())
47 .field("distance_from_sync", &self.distance_from_sync())
48 .field("input_buffer", &self.input_buffer())
49 .field("output_buffer", &self.output_buffer())
50 .field("deadline", &self.deadline());
51
52 b.finish()
53 }
54}
55
56impl<'a> VideoCodecFrame<'a> {
57 pub(crate) unsafe fn new<T: HasStreamLock>(
59 frame: *mut ffi::GstVideoCodecFrame,
60 element: &'a T,
61 ) -> Self {
62 skip_assert_initialized!();
63 let stream_lock = element.stream_lock();
64 glib::ffi::g_rec_mutex_lock(stream_lock);
65 Self { frame, element }
66 }
67
68 #[doc(alias = "get_flags")]
69 #[inline]
70 pub fn flags(&self) -> VideoCodecFrameFlags {
71 let flags = unsafe { (*self.to_glib_none().0).flags };
72 VideoCodecFrameFlags::from_bits_truncate(flags)
73 }
74
75 #[inline]
76 pub fn set_flags(&mut self, flags: VideoCodecFrameFlags) {
77 unsafe { (*self.to_glib_none().0).flags |= flags.bits() }
78 }
79
80 #[inline]
81 pub fn unset_flags(&mut self, flags: VideoCodecFrameFlags) {
82 unsafe { (*self.to_glib_none().0).flags &= !flags.bits() }
83 }
84
85 #[doc(alias = "get_system_frame_number")]
86 #[inline]
87 pub fn system_frame_number(&self) -> u32 {
88 unsafe { (*self.to_glib_none().0).system_frame_number }
89 }
90
91 #[doc(alias = "get_decode_frame_number")]
92 #[inline]
93 pub fn decode_frame_number(&self) -> u32 {
94 unsafe { (*self.to_glib_none().0).decode_frame_number }
95 }
96
97 #[doc(alias = "get_presentation_frame_number")]
98 #[inline]
99 pub fn presentation_frame_number(&self) -> u32 {
100 unsafe { (*self.to_glib_none().0).presentation_frame_number }
101 }
102
103 #[doc(alias = "get_dts")]
104 #[inline]
105 pub fn dts(&self) -> Option<gst::ClockTime> {
106 unsafe { from_glib((*self.to_glib_none().0).dts) }
107 }
108
109 #[inline]
110 pub fn set_dts(&mut self, dts: impl Into<Option<gst::ClockTime>>) {
111 unsafe {
112 (*self.to_glib_none().0).dts = dts.into().into_glib();
113 }
114 }
115
116 #[doc(alias = "get_pts")]
117 #[inline]
118 pub fn pts(&self) -> Option<gst::ClockTime> {
119 unsafe { from_glib((*self.to_glib_none().0).pts) }
120 }
121
122 #[inline]
123 pub fn set_pts(&mut self, pts: impl Into<Option<gst::ClockTime>>) {
124 unsafe {
125 (*self.to_glib_none().0).pts = pts.into().into_glib();
126 }
127 }
128
129 #[doc(alias = "get_duration")]
130 #[inline]
131 pub fn duration(&self) -> Option<gst::ClockTime> {
132 unsafe { from_glib((*self.to_glib_none().0).duration) }
133 }
134
135 #[inline]
136 pub fn set_duration(&mut self, duration: impl Into<Option<gst::ClockTime>>) {
137 unsafe {
138 (*self.to_glib_none().0).duration = duration.into().into_glib();
139 }
140 }
141
142 #[doc(alias = "get_distance_from_sync")]
143 #[inline]
144 pub fn distance_from_sync(&self) -> i32 {
145 unsafe { (*self.to_glib_none().0).distance_from_sync }
146 }
147
148 #[doc(alias = "get_input_buffer")]
149 #[inline]
150 pub fn input_buffer(&self) -> Option<&gst::BufferRef> {
151 unsafe {
152 let ptr = (*self.to_glib_none().0).input_buffer;
153 if ptr.is_null() {
154 None
155 } else {
156 Some(gst::BufferRef::from_ptr(ptr))
157 }
158 }
159 }
160
161 #[doc(alias = "get_input_buffer")]
162 #[inline]
163 pub fn input_buffer_owned(&self) -> Option<gst::Buffer> {
164 unsafe {
165 let ptr = (*self.to_glib_none().0).input_buffer;
166 if ptr.is_null() {
167 None
168 } else {
169 Some(from_glib_none(ptr))
170 }
171 }
172 }
173
174 #[doc(alias = "get_output_buffer")]
175 #[inline]
176 pub fn output_buffer(&self) -> Option<&gst::BufferRef> {
177 unsafe {
178 let ptr = (*self.to_glib_none().0).output_buffer;
179 if ptr.is_null() {
180 None
181 } else {
182 Some(gst::BufferRef::from_ptr(ptr))
183 }
184 }
185 }
186
187 #[doc(alias = "get_output_buffer_mut")]
188 pub fn output_buffer_mut(&mut self) -> Option<&mut gst::BufferRef> {
189 unsafe {
190 let ptr = (*self.to_glib_none().0).output_buffer;
191 if ptr.is_null() {
192 None
193 } else {
194 let writable: bool = from_glib(gst::ffi::gst_mini_object_is_writable(
195 ptr as *const gst::ffi::GstMiniObject,
196 ));
197 debug_assert!(writable);
198
199 Some(gst::BufferRef::from_mut_ptr(ptr))
200 }
201 }
202 }
203
204 pub fn set_output_buffer(&mut self, output_buffer: gst::Buffer) {
205 unsafe {
206 assert!(output_buffer.is_writable());
207 let prev = (*self.to_glib_none().0).output_buffer;
208
209 if !prev.is_null() {
210 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject);
211 }
212
213 (*self.to_glib_none().0).output_buffer = output_buffer.into_glib_ptr();
214 }
215 }
216
217 #[doc(alias = "get_deadline")]
218 #[inline]
219 pub fn deadline(&self) -> Option<gst::ClockTime> {
220 unsafe { from_glib((*self.to_glib_none().0).deadline) }
221 }
222
223 #[cfg(feature = "v1_20")]
224 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
225 #[doc(alias = "gst_video_decoder_get_processed_subframe_index")]
226 #[inline]
227 pub fn subframes_processed(&self) -> u32 {
228 unsafe { (*self.to_glib_none().0).abidata.ABI.subframes_processed }
229 }
230
231 #[cfg(feature = "v1_20")]
232 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
233 #[doc(alias = "gst_video_decoder_get_input_subframe_index")]
234 #[inline]
235 pub fn num_subframes(&self) -> u32 {
236 unsafe { (*self.to_glib_none().0).abidata.ABI.num_subframes }
237 }
238}
239
240impl IntoGlibPtr<*mut ffi::GstVideoCodecFrame> for VideoCodecFrame<'_> {
241 #[inline]
242 fn into_glib_ptr(self) -> *mut ffi::GstVideoCodecFrame {
243 let stream_lock = self.element.stream_lock();
244 unsafe {
245 glib::ffi::g_rec_mutex_unlock(stream_lock);
246 }
247
248 let s = mem::ManuallyDrop::new(self);
249 s.to_glib_none().0
250 }
251}
252
253impl Drop for VideoCodecFrame<'_> {
254 #[inline]
255 fn drop(&mut self) {
256 unsafe {
257 let stream_lock = self.element.stream_lock();
258 glib::ffi::g_rec_mutex_unlock(stream_lock);
259
260 ffi::gst_video_codec_frame_unref(self.frame);
261 }
262 }
263}