gstreamer/
buffer_pool.rs

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