gstreamer_video/
video_codec_state.rs1use 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 unsafe {
95 let stream_lock = element.stream_lock();
96 glib::ffi::g_rec_mutex_lock(stream_lock);
97 Self {
98 state,
99 context: InNegotiation { element },
100 phantom: PhantomData,
101 }
102 }
103 }
104}
105
106impl<'a, T: VideoCodecStateContext<'a>> VideoCodecState<'a, T> {
107 #[doc(alias = "get_info")]
108 #[inline]
109 pub fn info(&self) -> &VideoInfo {
110 unsafe {
111 &*(&(*self.as_mut_ptr()).info as *const ffi::GstVideoInfo as *const crate::VideoInfo)
112 }
113 }
114
115 #[doc(alias = "get_caps")]
116 #[inline]
117 pub fn caps(&self) -> Option<&gst::CapsRef> {
118 unsafe {
119 let ptr = (*self.as_mut_ptr()).caps;
120
121 if ptr.is_null() {
122 None
123 } else {
124 Some(gst::CapsRef::from_ptr(ptr))
125 }
126 }
127 }
128
129 #[doc(alias = "get_caps")]
130 #[inline]
131 pub fn caps_owned(&self) -> Option<gst::Caps> {
132 unsafe { from_glib_none((*self.as_mut_ptr()).caps) }
133 }
134
135 #[doc(alias = "get_codec_data")]
136 #[inline]
137 pub fn codec_data(&self) -> Option<&gst::BufferRef> {
138 unsafe {
139 let ptr = (*self.as_mut_ptr()).codec_data;
140
141 if ptr.is_null() {
142 None
143 } else {
144 Some(gst::BufferRef::from_ptr(ptr))
145 }
146 }
147 }
148
149 #[doc(alias = "get_codec_data")]
150 #[inline]
151 pub fn codec_data_owned(&self) -> Option<gst::Buffer> {
152 unsafe { from_glib_none((*self.as_mut_ptr()).codec_data) }
153 }
154
155 #[doc(alias = "get_allocation_caps")]
156 #[inline]
157 pub fn allocation_caps(&self) -> Option<&gst::CapsRef> {
158 unsafe {
159 let ptr = (*self.as_mut_ptr()).allocation_caps;
160
161 if ptr.is_null() {
162 None
163 } else {
164 Some(gst::CapsRef::from_ptr(ptr))
165 }
166 }
167 }
168
169 #[doc(alias = "get_allocation_caps")]
170 #[inline]
171 pub fn allocation_caps_owned(&self) -> Option<gst::Caps> {
172 unsafe { from_glib_none((*self.as_mut_ptr()).allocation_caps) }
173 }
174
175 #[doc(hidden)]
176 #[inline]
177 pub fn as_mut_ptr(&self) -> *mut ffi::GstVideoCodecState {
178 self.state
179 }
180}
181
182impl<'a, T: VideoCodecStateContext<'a>> Drop for VideoCodecState<'a, T> {
183 #[inline]
184 fn drop(&mut self) {
185 unsafe {
186 if let Some(element) = self.context.element() {
187 let stream_lock = element.stream_lock();
188 glib::ffi::g_rec_mutex_unlock(stream_lock);
189 }
190 ffi::gst_video_codec_state_unref(self.state);
191 }
192 }
193}
194
195impl<'a> VideoCodecState<'a, InNegotiation<'a>> {
196 #[inline]
197 pub fn set_info(&mut self, info: VideoInfo) {
198 unsafe {
199 ptr::write(&mut (*self.as_mut_ptr()).info, *(info.to_glib_none().0));
200 }
201 }
202
203 #[inline]
204 pub fn set_caps(&mut self, caps: &gst::Caps) {
205 unsafe {
206 let prev = (*self.as_mut_ptr()).caps;
207
208 if !prev.is_null() {
209 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
210 }
211
212 ptr::write(
213 &mut (*self.as_mut_ptr()).caps,
214 gst::ffi::gst_mini_object_ref(caps.as_mut_ptr() as *mut _) as *mut _,
215 );
216 }
217 }
218
219 #[inline]
220 pub fn set_codec_data(&mut self, codec_data: &gst::Buffer) {
221 unsafe {
222 let prev = (*self.as_mut_ptr()).codec_data;
223
224 if !prev.is_null() {
225 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
226 }
227
228 ptr::write(
229 &mut (*self.as_mut_ptr()).codec_data,
230 gst::ffi::gst_mini_object_ref(codec_data.as_mut_ptr() as *mut _) as *mut _,
231 );
232 }
233 }
234
235 #[inline]
236 pub fn set_allocation_caps(&mut self, allocation_caps: &gst::Caps) {
237 unsafe {
238 let prev = (*self.as_mut_ptr()).allocation_caps;
239
240 if !prev.is_null() {
241 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
242 }
243
244 ptr::write(
245 &mut (*self.as_mut_ptr()).allocation_caps,
246 gst::ffi::gst_mini_object_ref(allocation_caps.as_mut_ptr() as *mut _) as *mut _,
247 );
248 }
249 }
250}
251
252impl Clone for VideoCodecState<'_, Readable> {
253 #[inline]
254 fn clone(&self) -> Self {
255 unsafe {
256 let state = ffi::gst_video_codec_state_ref(self.state);
257 Self::new(state)
258 }
259 }
260}
261
262unsafe impl Send for VideoCodecState<'_, Readable> {}
263unsafe impl Sync for VideoCodecState<'_, Readable> {}