gstreamer_video/
video_codec_state.rs
1use std::{fmt, marker::PhantomData, ptr};
4
5use glib::translate::*;
6
7use crate::{ffi, utils::HasStreamLock, video_info::VideoInfo};
8
9pub trait VideoCodecStateContext<'a> {
10 #[doc(alias = "get_element")]
11 fn element(&self) -> Option<&'a dyn HasStreamLock>;
12 #[doc(alias = "get_element_as_ptr")]
13 fn element_as_ptr(&self) -> *const gst::ffi::GstElement;
14}
15
16pub struct InNegotiation<'a> {
17 element: &'a dyn HasStreamLock,
20}
21pub struct Readable {}
22
23impl<'a> VideoCodecStateContext<'a> for InNegotiation<'a> {
24 #[inline]
25 fn element(&self) -> Option<&'a dyn HasStreamLock> {
26 Some(self.element)
27 }
28
29 #[inline]
30 fn element_as_ptr(&self) -> *const gst::ffi::GstElement {
31 self.element.element_as_ptr()
32 }
33}
34
35impl<'a> VideoCodecStateContext<'a> for Readable {
36 #[inline]
37 fn element(&self) -> Option<&'a dyn HasStreamLock> {
38 None
39 }
40
41 #[inline]
42 fn element_as_ptr(&self) -> *const gst::ffi::GstElement {
43 ptr::null()
44 }
45}
46
47pub struct VideoCodecState<'a, T: VideoCodecStateContext<'a>> {
57 state: *mut ffi::GstVideoCodecState,
58 pub(crate) context: T,
59 phantom: PhantomData<&'a T>,
60}
61
62impl<'a, T: VideoCodecStateContext<'a>> fmt::Debug for VideoCodecState<'a, T> {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 f.debug_struct("VideoCodecState")
65 .field("info", &self.info())
66 .field("caps", &self.caps())
67 .field("codec_data", &self.codec_data())
68 .field("allocation_caps", &self.allocation_caps())
69 .finish()
70 }
71}
72
73impl VideoCodecState<'_, Readable> {
74 #[inline]
76 pub(crate) unsafe fn new(state: *mut ffi::GstVideoCodecState) -> Self {
77 skip_assert_initialized!();
78 Self {
79 state,
80 context: Readable {},
81 phantom: PhantomData,
82 }
83 }
84}
85
86impl<'a> VideoCodecState<'a, InNegotiation<'a>> {
87 #[inline]
89 pub(crate) unsafe fn new<T: HasStreamLock>(
90 state: *mut ffi::GstVideoCodecState,
91 element: &'a T,
92 ) -> Self {
93 skip_assert_initialized!();
94 let stream_lock = element.stream_lock();
95 glib::ffi::g_rec_mutex_lock(stream_lock);
96 Self {
97 state,
98 context: InNegotiation { element },
99 phantom: PhantomData,
100 }
101 }
102}
103
104impl<'a, T: VideoCodecStateContext<'a>> VideoCodecState<'a, T> {
105 #[doc(alias = "get_info")]
106 #[inline]
107 pub fn info(&self) -> &VideoInfo {
108 unsafe {
109 &*(&(*self.as_mut_ptr()).info as *const ffi::GstVideoInfo as *const crate::VideoInfo)
110 }
111 }
112
113 #[doc(alias = "get_caps")]
114 #[inline]
115 pub fn caps(&self) -> Option<&gst::CapsRef> {
116 unsafe {
117 let ptr = (*self.as_mut_ptr()).caps;
118
119 if ptr.is_null() {
120 None
121 } else {
122 Some(gst::CapsRef::from_ptr(ptr))
123 }
124 }
125 }
126
127 #[doc(alias = "get_caps")]
128 #[inline]
129 pub fn caps_owned(&self) -> Option<gst::Caps> {
130 unsafe { from_glib_none((*self.as_mut_ptr()).caps) }
131 }
132
133 #[doc(alias = "get_codec_data")]
134 #[inline]
135 pub fn codec_data(&self) -> Option<&gst::BufferRef> {
136 unsafe {
137 let ptr = (*self.as_mut_ptr()).codec_data;
138
139 if ptr.is_null() {
140 None
141 } else {
142 Some(gst::BufferRef::from_ptr(ptr))
143 }
144 }
145 }
146
147 #[doc(alias = "get_codec_data")]
148 #[inline]
149 pub fn codec_data_owned(&self) -> Option<gst::Buffer> {
150 unsafe { from_glib_none((*self.as_mut_ptr()).codec_data) }
151 }
152
153 #[doc(alias = "get_allocation_caps")]
154 #[inline]
155 pub fn allocation_caps(&self) -> Option<&gst::CapsRef> {
156 unsafe {
157 let ptr = (*self.as_mut_ptr()).allocation_caps;
158
159 if ptr.is_null() {
160 None
161 } else {
162 Some(gst::CapsRef::from_ptr(ptr))
163 }
164 }
165 }
166
167 #[doc(alias = "get_allocation_caps")]
168 #[inline]
169 pub fn allocation_caps_owned(&self) -> Option<gst::Caps> {
170 unsafe { from_glib_none((*self.as_mut_ptr()).allocation_caps) }
171 }
172
173 #[doc(hidden)]
174 #[inline]
175 pub fn as_mut_ptr(&self) -> *mut ffi::GstVideoCodecState {
176 self.state
177 }
178}
179
180impl<'a, T: VideoCodecStateContext<'a>> Drop for VideoCodecState<'a, T> {
181 #[inline]
182 fn drop(&mut self) {
183 unsafe {
184 if let Some(element) = self.context.element() {
185 let stream_lock = element.stream_lock();
186 glib::ffi::g_rec_mutex_unlock(stream_lock);
187 }
188 ffi::gst_video_codec_state_unref(self.state);
189 }
190 }
191}
192
193impl<'a> VideoCodecState<'a, InNegotiation<'a>> {
194 #[inline]
195 pub fn set_info(&mut self, info: VideoInfo) {
196 unsafe {
197 ptr::write(&mut (*self.as_mut_ptr()).info, *(info.to_glib_none().0));
198 }
199 }
200
201 #[inline]
202 pub fn set_caps(&mut self, caps: &gst::Caps) {
203 unsafe {
204 let prev = (*self.as_mut_ptr()).caps;
205
206 if !prev.is_null() {
207 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
208 }
209
210 ptr::write(
211 &mut (*self.as_mut_ptr()).caps,
212 gst::ffi::gst_mini_object_ref(caps.as_mut_ptr() as *mut _) as *mut _,
213 );
214 }
215 }
216
217 #[inline]
218 pub fn set_codec_data(&mut self, codec_data: &gst::Buffer) {
219 unsafe {
220 let prev = (*self.as_mut_ptr()).codec_data;
221
222 if !prev.is_null() {
223 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
224 }
225
226 ptr::write(
227 &mut (*self.as_mut_ptr()).codec_data,
228 gst::ffi::gst_mini_object_ref(codec_data.as_mut_ptr() as *mut _) as *mut _,
229 );
230 }
231 }
232
233 #[inline]
234 pub fn set_allocation_caps(&mut self, allocation_caps: &gst::Caps) {
235 unsafe {
236 let prev = (*self.as_mut_ptr()).allocation_caps;
237
238 if !prev.is_null() {
239 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
240 }
241
242 ptr::write(
243 &mut (*self.as_mut_ptr()).allocation_caps,
244 gst::ffi::gst_mini_object_ref(allocation_caps.as_mut_ptr() as *mut _) as *mut _,
245 );
246 }
247 }
248}
249
250impl Clone for VideoCodecState<'_, Readable> {
251 #[inline]
252 fn clone(&self) -> Self {
253 unsafe {
254 let state = ffi::gst_video_codec_state_ref(self.state);
255 Self::new(state)
256 }
257 }
258}
259
260unsafe impl Send for VideoCodecState<'_, Readable> {}
261unsafe impl Sync for VideoCodecState<'_, Readable> {}