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>> {
48 state: *mut ffi::GstVideoCodecState,
49 pub(crate) context: T,
50 phantom: PhantomData<&'a T>,
51}
52
53impl<'a, T: VideoCodecStateContext<'a>> fmt::Debug for VideoCodecState<'a, T> {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 f.debug_struct("VideoCodecState")
56 .field("info", &self.info())
57 .field("caps", &self.caps())
58 .field("codec_data", &self.codec_data())
59 .field("allocation_caps", &self.allocation_caps())
60 .finish()
61 }
62}
63
64impl VideoCodecState<'_, Readable> {
65 #[inline]
67 pub(crate) unsafe fn new(state: *mut ffi::GstVideoCodecState) -> Self {
68 skip_assert_initialized!();
69 Self {
70 state,
71 context: Readable {},
72 phantom: PhantomData,
73 }
74 }
75}
76
77impl<'a> VideoCodecState<'a, InNegotiation<'a>> {
78 #[inline]
80 pub(crate) unsafe fn new<T: HasStreamLock>(
81 state: *mut ffi::GstVideoCodecState,
82 element: &'a T,
83 ) -> Self {
84 skip_assert_initialized!();
85 unsafe {
86 let stream_lock = element.stream_lock();
87 glib::ffi::g_rec_mutex_lock(stream_lock);
88 Self {
89 state,
90 context: InNegotiation { element },
91 phantom: PhantomData,
92 }
93 }
94 }
95}
96
97impl<'a, T: VideoCodecStateContext<'a>> VideoCodecState<'a, T> {
98 #[doc(alias = "get_info")]
99 #[inline]
100 pub fn info(&self) -> &VideoInfo {
101 unsafe {
102 &*(&(*self.as_mut_ptr()).info as *const ffi::GstVideoInfo as *const crate::VideoInfo)
103 }
104 }
105
106 #[doc(alias = "get_caps")]
107 #[inline]
108 pub fn caps(&self) -> Option<&gst::CapsRef> {
109 unsafe {
110 let ptr = (*self.as_mut_ptr()).caps;
111
112 if ptr.is_null() {
113 None
114 } else {
115 Some(gst::CapsRef::from_ptr(ptr))
116 }
117 }
118 }
119
120 #[doc(alias = "get_caps")]
121 #[inline]
122 pub fn caps_owned(&self) -> Option<gst::Caps> {
123 unsafe { from_glib_none((*self.as_mut_ptr()).caps) }
124 }
125
126 #[doc(alias = "get_codec_data")]
127 #[inline]
128 pub fn codec_data(&self) -> Option<&gst::BufferRef> {
129 unsafe {
130 let ptr = (*self.as_mut_ptr()).codec_data;
131
132 if ptr.is_null() {
133 None
134 } else {
135 Some(gst::BufferRef::from_ptr(ptr))
136 }
137 }
138 }
139
140 #[doc(alias = "get_codec_data")]
141 #[inline]
142 pub fn codec_data_owned(&self) -> Option<gst::Buffer> {
143 unsafe { from_glib_none((*self.as_mut_ptr()).codec_data) }
144 }
145
146 #[doc(alias = "get_allocation_caps")]
147 #[inline]
148 pub fn allocation_caps(&self) -> Option<&gst::CapsRef> {
149 unsafe {
150 let ptr = (*self.as_mut_ptr()).allocation_caps;
151
152 if ptr.is_null() {
153 None
154 } else {
155 Some(gst::CapsRef::from_ptr(ptr))
156 }
157 }
158 }
159
160 #[doc(alias = "get_allocation_caps")]
161 #[inline]
162 pub fn allocation_caps_owned(&self) -> Option<gst::Caps> {
163 unsafe { from_glib_none((*self.as_mut_ptr()).allocation_caps) }
164 }
165
166 #[doc(hidden)]
167 #[inline]
168 pub fn as_mut_ptr(&self) -> *mut ffi::GstVideoCodecState {
169 self.state
170 }
171}
172
173impl<'a, T: VideoCodecStateContext<'a>> Drop for VideoCodecState<'a, T> {
174 #[inline]
175 fn drop(&mut self) {
176 unsafe {
177 if let Some(element) = self.context.element() {
178 let stream_lock = element.stream_lock();
179 glib::ffi::g_rec_mutex_unlock(stream_lock);
180 }
181 ffi::gst_video_codec_state_unref(self.state);
182 }
183 }
184}
185
186impl<'a> VideoCodecState<'a, InNegotiation<'a>> {
187 #[inline]
188 pub fn set_info(&mut self, info: VideoInfo) {
189 unsafe {
190 ptr::write(&mut (*self.as_mut_ptr()).info, *(info.to_glib_none().0));
191 }
192 }
193
194 #[inline]
195 pub fn set_caps(&mut self, caps: &gst::Caps) {
196 unsafe {
197 let prev = (*self.as_mut_ptr()).caps;
198
199 if !prev.is_null() {
200 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
201 }
202
203 ptr::write(
204 &mut (*self.as_mut_ptr()).caps,
205 gst::ffi::gst_mini_object_ref(caps.as_mut_ptr() as *mut _) as *mut _,
206 );
207 }
208 }
209
210 #[inline]
211 pub fn set_codec_data(&mut self, codec_data: &gst::Buffer) {
212 unsafe {
213 let prev = (*self.as_mut_ptr()).codec_data;
214
215 if !prev.is_null() {
216 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
217 }
218
219 ptr::write(
220 &mut (*self.as_mut_ptr()).codec_data,
221 gst::ffi::gst_mini_object_ref(codec_data.as_mut_ptr() as *mut _) as *mut _,
222 );
223 }
224 }
225
226 #[inline]
227 pub fn set_allocation_caps(&mut self, allocation_caps: &gst::Caps) {
228 unsafe {
229 let prev = (*self.as_mut_ptr()).allocation_caps;
230
231 if !prev.is_null() {
232 gst::ffi::gst_mini_object_unref(prev as *mut gst::ffi::GstMiniObject)
233 }
234
235 ptr::write(
236 &mut (*self.as_mut_ptr()).allocation_caps,
237 gst::ffi::gst_mini_object_ref(allocation_caps.as_mut_ptr() as *mut _) as *mut _,
238 );
239 }
240 }
241}
242
243impl Clone for VideoCodecState<'_, Readable> {
244 #[inline]
245 fn clone(&self) -> Self {
246 unsafe {
247 let state = ffi::gst_video_codec_state_ref(self.state);
248 Self::new(state)
249 }
250 }
251}
252
253unsafe impl Send for VideoCodecState<'_, Readable> {}
254unsafe impl Sync for VideoCodecState<'_, Readable> {}