1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{ |
4 | marker::PhantomData, |
5 | mem, ops, |
6 | ops::{Deref, DerefMut}, |
7 | ptr, |
8 | }; |
9 | |
10 | use glib::{prelude::*, translate::*}; |
11 | |
12 | use crate::{AllocationParams, Allocator, BufferPool, Structure, StructureRef}; |
13 | |
14 | #[derive (Debug, Clone, PartialEq, Eq)] |
15 | #[repr (transparent)] |
16 | pub struct BufferPoolConfig(Structure); |
17 | |
18 | impl Deref for BufferPoolConfig { |
19 | type Target = BufferPoolConfigRef; |
20 | |
21 | #[inline ] |
22 | fn deref(&self) -> &BufferPoolConfigRef { |
23 | unsafe { &*(self.0.as_ptr() as *const StructureRef as *const BufferPoolConfigRef) } |
24 | } |
25 | } |
26 | |
27 | impl DerefMut for BufferPoolConfig { |
28 | #[inline ] |
29 | fn deref_mut(&mut self) -> &mut BufferPoolConfigRef { |
30 | unsafe { &mut *(self.0.as_ptr() as *mut StructureRef as *mut BufferPoolConfigRef) } |
31 | } |
32 | } |
33 | |
34 | impl AsRef<BufferPoolConfigRef> for BufferPoolConfig { |
35 | #[inline ] |
36 | fn as_ref(&self) -> &BufferPoolConfigRef { |
37 | self.deref() |
38 | } |
39 | } |
40 | |
41 | impl AsMut<BufferPoolConfigRef> for BufferPoolConfig { |
42 | #[inline ] |
43 | fn as_mut(&mut self) -> &mut BufferPoolConfigRef { |
44 | self.deref_mut() |
45 | } |
46 | } |
47 | |
48 | #[derive (Debug)] |
49 | #[repr (transparent)] |
50 | pub struct BufferPoolConfigRef(StructureRef); |
51 | |
52 | impl BufferPoolConfigRef { |
53 | #[inline ] |
54 | pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a BufferPoolConfigRef { |
55 | debug_assert!(!ptr.is_null()); |
56 | |
57 | &*(ptr as *mut StructureRef as *mut BufferPoolConfigRef) |
58 | } |
59 | |
60 | #[inline ] |
61 | pub unsafe fn from_glib_borrow_mut<'a>( |
62 | ptr: *mut ffi::GstStructure, |
63 | ) -> &'a mut BufferPoolConfigRef { |
64 | debug_assert!(!ptr.is_null()); |
65 | |
66 | &mut *(ptr as *mut StructureRef as *mut BufferPoolConfigRef) |
67 | } |
68 | |
69 | #[inline ] |
70 | pub fn as_ptr(&self) -> *const ffi::GstStructure { |
71 | self as *const Self as *const ffi::GstStructure |
72 | } |
73 | |
74 | #[inline ] |
75 | pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure { |
76 | self as *const Self as *mut ffi::GstStructure |
77 | } |
78 | } |
79 | |
80 | impl ops::Deref for BufferPoolConfigRef { |
81 | type Target = crate::StructureRef; |
82 | |
83 | #[inline ] |
84 | fn deref(&self) -> &crate::StructureRef { |
85 | &self.0 |
86 | } |
87 | } |
88 | |
89 | impl ops::DerefMut for BufferPoolConfigRef { |
90 | #[inline ] |
91 | fn deref_mut(&mut self) -> &mut crate::StructureRef { |
92 | &mut self.0 |
93 | } |
94 | } |
95 | |
96 | impl AsRef<crate::StructureRef> for BufferPoolConfigRef { |
97 | #[inline ] |
98 | fn as_ref(&self) -> &crate::StructureRef { |
99 | &self.0 |
100 | } |
101 | } |
102 | |
103 | impl AsMut<crate::StructureRef> for BufferPoolConfigRef { |
104 | #[inline ] |
105 | fn as_mut(&mut self) -> &mut crate::StructureRef { |
106 | &mut self.0 |
107 | } |
108 | } |
109 | |
110 | impl BufferPoolConfigRef { |
111 | #[doc (alias = "gst_buffer_pool_config_add_option" )] |
112 | pub fn add_option(&mut self, option: &str) { |
113 | unsafe { |
114 | ffi::gst_buffer_pool_config_add_option(self.0.as_mut_ptr(), option.to_glib_none().0); |
115 | } |
116 | } |
117 | |
118 | #[doc (alias = "gst_buffer_pool_config_has_option" )] |
119 | pub fn has_option(&self, option: &str) -> bool { |
120 | unsafe { |
121 | from_glib(ffi::gst_buffer_pool_config_has_option( |
122 | self.0.as_mut_ptr(), |
123 | option.to_glib_none().0, |
124 | )) |
125 | } |
126 | } |
127 | |
128 | #[doc (alias = "get_options" )] |
129 | #[doc (alias = "gst_buffer_pool_config_n_options" )] |
130 | #[doc (alias = "gst_buffer_pool_config_get_option" )] |
131 | pub fn options(&self) -> Vec<String> { |
132 | unsafe { |
133 | let n = ffi::gst_buffer_pool_config_n_options(self.0.as_mut_ptr()) as usize; |
134 | let mut options = Vec::with_capacity(n); |
135 | |
136 | for i in 0..n { |
137 | options.push(from_glib_none(ffi::gst_buffer_pool_config_get_option( |
138 | self.0.as_mut_ptr(), |
139 | i as u32, |
140 | ))); |
141 | } |
142 | |
143 | options |
144 | } |
145 | } |
146 | |
147 | #[doc (alias = "gst_buffer_pool_config_set_params" )] |
148 | pub fn set_params( |
149 | &mut self, |
150 | caps: Option<&crate::Caps>, |
151 | size: u32, |
152 | min_buffers: u32, |
153 | max_buffers: u32, |
154 | ) { |
155 | unsafe { |
156 | ffi::gst_buffer_pool_config_set_params( |
157 | self.0.as_mut_ptr(), |
158 | caps.to_glib_none().0, |
159 | size, |
160 | min_buffers, |
161 | max_buffers, |
162 | ); |
163 | } |
164 | } |
165 | |
166 | #[doc (alias = "get_params" )] |
167 | #[doc (alias = "gst_buffer_pool_config_get_params" )] |
168 | pub fn params(&self) -> Option<(Option<crate::Caps>, u32, u32, u32)> { |
169 | unsafe { |
170 | let mut caps = ptr::null_mut(); |
171 | let mut size = mem::MaybeUninit::uninit(); |
172 | let mut min_buffers = mem::MaybeUninit::uninit(); |
173 | let mut max_buffers = mem::MaybeUninit::uninit(); |
174 | |
175 | let ret: bool = from_glib(ffi::gst_buffer_pool_config_get_params( |
176 | self.0.as_mut_ptr(), |
177 | &mut caps, |
178 | size.as_mut_ptr(), |
179 | min_buffers.as_mut_ptr(), |
180 | max_buffers.as_mut_ptr(), |
181 | )); |
182 | if !ret { |
183 | return None; |
184 | } |
185 | |
186 | Some(( |
187 | from_glib_none(caps), |
188 | size.assume_init(), |
189 | min_buffers.assume_init(), |
190 | max_buffers.assume_init(), |
191 | )) |
192 | } |
193 | } |
194 | |
195 | #[doc (alias = "gst_buffer_pool_config_validate_params" )] |
196 | pub fn validate_params( |
197 | &self, |
198 | caps: Option<&crate::Caps>, |
199 | size: u32, |
200 | min_buffers: u32, |
201 | max_buffers: u32, |
202 | ) -> Result<(), glib::BoolError> { |
203 | unsafe { |
204 | glib::result_from_gboolean!( |
205 | ffi::gst_buffer_pool_config_validate_params( |
206 | self.0.as_mut_ptr(), |
207 | caps.to_glib_none().0, |
208 | size, |
209 | min_buffers, |
210 | max_buffers, |
211 | ), |
212 | "Parameters are not valid in this context" |
213 | ) |
214 | } |
215 | } |
216 | |
217 | #[doc (alias = "get_allocator" )] |
218 | #[doc (alias = "gst_buffer_pool_config_get_allocator" )] |
219 | pub fn allocator(&self) -> Option<(Option<Allocator>, AllocationParams)> { |
220 | unsafe { |
221 | let mut allocator = ptr::null_mut(); |
222 | let mut params = mem::MaybeUninit::uninit(); |
223 | let ret = from_glib(ffi::gst_buffer_pool_config_get_allocator( |
224 | self.0.as_mut_ptr(), |
225 | &mut allocator, |
226 | params.as_mut_ptr(), |
227 | )); |
228 | if ret { |
229 | Some((from_glib_none(allocator), params.assume_init().into())) |
230 | } else { |
231 | None |
232 | } |
233 | } |
234 | } |
235 | |
236 | #[doc (alias = "gst_buffer_pool_config_set_allocator" )] |
237 | pub fn set_allocator(&self, allocator: Option<&Allocator>, params: Option<&AllocationParams>) { |
238 | assert!(allocator.is_some() || params.is_some()); |
239 | unsafe { |
240 | ffi::gst_buffer_pool_config_set_allocator( |
241 | self.0.as_mut_ptr(), |
242 | allocator.to_glib_none().0, |
243 | match params { |
244 | Some(val) => val.as_ptr(), |
245 | None => ptr::null(), |
246 | }, |
247 | ) |
248 | } |
249 | } |
250 | // TODO: options iterator |
251 | } |
252 | |
253 | #[derive (Debug)] |
254 | #[doc (alias = "GstBufferPoolAcquireParams" )] |
255 | pub struct BufferPoolAcquireParams(ffi::GstBufferPoolAcquireParams); |
256 | |
257 | unsafe impl Send for BufferPoolAcquireParams {} |
258 | unsafe impl Sync for BufferPoolAcquireParams {} |
259 | |
260 | impl BufferPoolAcquireParams { |
261 | pub fn with_flags(flags: crate::BufferPoolAcquireFlags) -> Self { |
262 | skip_assert_initialized!(); |
263 | BufferPoolAcquireParams(ffi::GstBufferPoolAcquireParams { |
264 | format: ffi::GST_FORMAT_UNDEFINED, |
265 | start: -1, |
266 | stop: -1, |
267 | flags: flags.into_glib(), |
268 | _gst_reserved: [ptr::null_mut(); 4], |
269 | }) |
270 | } |
271 | |
272 | pub fn with_start_stop<T: crate::format::SpecificFormattedValue>( |
273 | start: T, |
274 | stop: T, |
275 | flags: crate::BufferPoolAcquireFlags, |
276 | ) -> Self { |
277 | skip_assert_initialized!(); |
278 | unsafe { |
279 | BufferPoolAcquireParams(ffi::GstBufferPoolAcquireParams { |
280 | format: start.format().into_glib(), |
281 | start: start.into_raw_value(), |
282 | stop: stop.into_raw_value(), |
283 | flags: flags.into_glib(), |
284 | _gst_reserved: [ptr::null_mut(); 4], |
285 | }) |
286 | } |
287 | } |
288 | |
289 | pub fn flags(&self) -> crate::BufferPoolAcquireFlags { |
290 | unsafe { from_glib(self.0.flags) } |
291 | } |
292 | |
293 | pub fn format(&self) -> crate::Format { |
294 | unsafe { from_glib(self.0.format) } |
295 | } |
296 | |
297 | pub fn start(&self) -> crate::GenericFormattedValue { |
298 | unsafe { crate::GenericFormattedValue::new(from_glib(self.0.format), self.0.start) } |
299 | } |
300 | |
301 | pub fn stop(&self) -> crate::GenericFormattedValue { |
302 | unsafe { crate::GenericFormattedValue::new(from_glib(self.0.format), self.0.stop) } |
303 | } |
304 | } |
305 | |
306 | impl PartialEq for BufferPoolAcquireParams { |
307 | fn eq(&self, other: &Self) -> bool { |
308 | self.format() == other.format() |
309 | && self.start() == other.start() |
310 | && self.stop() == other.stop() |
311 | } |
312 | } |
313 | |
314 | impl Eq for BufferPoolAcquireParams {} |
315 | |
316 | #[doc (hidden)] |
317 | impl<'a> ToGlibPtr<'a, *const ffi::GstBufferPoolAcquireParams> for BufferPoolAcquireParams { |
318 | type Storage = PhantomData<&'a Self>; |
319 | |
320 | #[inline ] |
321 | fn to_glib_none( |
322 | &'a self, |
323 | ) -> glib::translate::Stash<'a, *const ffi::GstBufferPoolAcquireParams, Self> { |
324 | glib::translate::Stash(&self.0, PhantomData) |
325 | } |
326 | } |
327 | |
328 | #[doc (hidden)] |
329 | impl<'a> ToGlibPtrMut<'a, *mut ffi::GstBufferPoolAcquireParams> for BufferPoolAcquireParams { |
330 | type Storage = PhantomData<&'a mut Self>; |
331 | |
332 | #[inline ] |
333 | fn to_glib_none_mut( |
334 | &'a mut self, |
335 | ) -> glib::translate::StashMut<'a, *mut ffi::GstBufferPoolAcquireParams, Self> { |
336 | glib::translate::StashMut(&mut self.0, PhantomData) |
337 | } |
338 | } |
339 | |
340 | #[doc (hidden)] |
341 | impl FromGlibPtrNone<*mut ffi::GstBufferPoolAcquireParams> for BufferPoolAcquireParams { |
342 | #[inline ] |
343 | unsafe fn from_glib_none(ptr: *mut ffi::GstBufferPoolAcquireParams) -> Self { |
344 | Self(*ptr) |
345 | } |
346 | } |
347 | |
348 | mod sealed { |
349 | pub trait Sealed {} |
350 | impl<T: super::IsA<super::BufferPool>> Sealed for T {} |
351 | } |
352 | |
353 | pub trait BufferPoolExtManual: sealed::Sealed + IsA<BufferPool> + 'static { |
354 | #[doc (alias = "get_config" )] |
355 | #[doc (alias = "gst_buffer_pool_get_config" )] |
356 | fn config(&self) -> BufferPoolConfig { |
357 | unsafe { |
358 | let ptr = ffi::gst_buffer_pool_get_config(self.as_ref().to_glib_none().0); |
359 | BufferPoolConfig(from_glib_full(ptr)) |
360 | } |
361 | } |
362 | |
363 | #[doc (alias = "gst_buffer_pool_set_config" )] |
364 | fn set_config(&self, config: BufferPoolConfig) -> Result<(), glib::error::BoolError> { |
365 | unsafe { |
366 | glib::result_from_gboolean!( |
367 | ffi::gst_buffer_pool_set_config( |
368 | self.as_ref().to_glib_none().0, |
369 | config.0.into_glib_ptr() |
370 | ), |
371 | "Failed to set config" , |
372 | ) |
373 | } |
374 | } |
375 | |
376 | fn is_flushing(&self) -> bool { |
377 | unsafe { |
378 | let stash = self.as_ref().to_glib_none(); |
379 | let ptr: *mut ffi::GstBufferPool = stash.0; |
380 | |
381 | from_glib((*ptr).flushing) |
382 | } |
383 | } |
384 | |
385 | #[doc (alias = "gst_buffer_pool_acquire_buffer" )] |
386 | fn acquire_buffer( |
387 | &self, |
388 | params: Option<&BufferPoolAcquireParams>, |
389 | ) -> Result<crate::Buffer, crate::FlowError> { |
390 | let params_ptr = params.to_glib_none().0 as *mut _; |
391 | |
392 | unsafe { |
393 | let mut buffer = ptr::null_mut(); |
394 | crate::FlowSuccess::try_from_glib(ffi::gst_buffer_pool_acquire_buffer( |
395 | self.as_ref().to_glib_none().0, |
396 | &mut buffer, |
397 | params_ptr, |
398 | )) |
399 | .map(|_| from_glib_full(buffer)) |
400 | } |
401 | } |
402 | } |
403 | |
404 | impl<O: IsA<BufferPool>> BufferPoolExtManual for O {} |
405 | |
406 | #[cfg (test)] |
407 | mod tests { |
408 | use super::*; |
409 | use crate::prelude::*; |
410 | |
411 | #[test ] |
412 | fn pool_with_params() { |
413 | crate::init().unwrap(); |
414 | |
415 | let pool = crate::BufferPool::new(); |
416 | let mut config = pool.config(); |
417 | config.set_params(Some(&crate::Caps::builder("foo/bar" ).build()), 1024, 0, 2); |
418 | pool.set_config(config).unwrap(); |
419 | |
420 | pool.set_active(true).unwrap(); |
421 | |
422 | let params = |
423 | crate::BufferPoolAcquireParams::with_flags(crate::BufferPoolAcquireFlags::DONTWAIT); |
424 | |
425 | let _buf1 = pool.acquire_buffer(Some(¶ms)).unwrap(); |
426 | let buf2 = pool.acquire_buffer(Some(¶ms)).unwrap(); |
427 | |
428 | assert!(pool.acquire_buffer(Some(¶ms)).is_err()); |
429 | |
430 | drop(buf2); |
431 | let _buf2 = pool.acquire_buffer(Some(¶ms)).unwrap(); |
432 | |
433 | pool.set_active(false).unwrap(); |
434 | } |
435 | |
436 | #[test ] |
437 | fn pool_no_params() { |
438 | crate::init().unwrap(); |
439 | |
440 | let pool = crate::BufferPool::new(); |
441 | let mut config = pool.config(); |
442 | config.set_params(None, 1024, 0, 2); |
443 | pool.set_config(config).unwrap(); |
444 | |
445 | pool.set_active(true).unwrap(); |
446 | let _buf1 = pool.acquire_buffer(None).unwrap(); |
447 | pool.set_active(false).unwrap(); |
448 | } |
449 | } |
450 | |