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