gstreamer/
bufferlist.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{
4    cmp, fmt,
5    ops::{ControlFlow, RangeBounds},
6    ptr,
7};
8
9use glib::translate::*;
10
11use crate::{Buffer, BufferRef, ffi};
12
13mini_object_wrapper!(BufferList, BufferListRef, ffi::GstBufferList, || {
14    ffi::gst_buffer_list_get_type()
15});
16
17impl BufferList {
18    #[doc(alias = "gst_buffer_list_new")]
19    pub fn new() -> Self {
20        assert_initialized_main_thread!();
21        unsafe { from_glib_full(ffi::gst_buffer_list_new()) }
22    }
23
24    #[doc(alias = "gst_buffer_list_new_sized")]
25    pub fn new_sized(size: usize) -> Self {
26        assert_initialized_main_thread!();
27        unsafe { from_glib_full(ffi::gst_buffer_list_new_sized(u32::try_from(size).unwrap())) }
28    }
29}
30
31impl BufferListRef {
32    #[doc(alias = "gst_buffer_list_insert")]
33    pub fn insert(&mut self, idx: impl Into<Option<usize>>, buffer: Buffer) {
34        unsafe {
35            let len = self.len();
36            debug_assert!(len <= u32::MAX as usize);
37
38            let idx = idx.into();
39            let idx = cmp::min(idx.unwrap_or(len), len) as i32;
40            ffi::gst_buffer_list_insert(self.as_mut_ptr(), idx, buffer.into_glib_ptr());
41        }
42    }
43
44    #[doc(alias = "gst_buffer_list_add")]
45    pub fn add(&mut self, buffer: Buffer) {
46        self.insert(None, buffer);
47    }
48
49    #[doc(alias = "gst_buffer_list_copy_deep")]
50    pub fn copy_deep(&self) -> BufferList {
51        unsafe { from_glib_full(ffi::gst_buffer_list_copy_deep(self.as_ptr())) }
52    }
53
54    fn buffer_range_to_start_end_idx(&self, range: impl RangeBounds<usize>) -> (usize, usize) {
55        let n = self.len();
56        debug_assert!(n <= u32::MAX as usize);
57
58        let start_idx = match range.start_bound() {
59            std::ops::Bound::Included(idx) => *idx,
60            std::ops::Bound::Excluded(idx) => idx.checked_add(1).unwrap(),
61            std::ops::Bound::Unbounded => 0,
62        };
63        assert!(start_idx < n);
64
65        let end_idx = match range.end_bound() {
66            std::ops::Bound::Included(idx) => idx.checked_add(1).unwrap(),
67            std::ops::Bound::Excluded(idx) => *idx,
68            std::ops::Bound::Unbounded => n,
69        };
70        assert!(end_idx <= n);
71
72        (start_idx, end_idx)
73    }
74
75    #[doc(alias = "gst_buffer_list_remove")]
76    pub fn remove(&mut self, range: impl RangeBounds<usize>) {
77        let (start_idx, end_idx) = self.buffer_range_to_start_end_idx(range);
78
79        unsafe {
80            ffi::gst_buffer_list_remove(
81                self.as_mut_ptr(),
82                start_idx as u32,
83                (end_idx - start_idx) as u32,
84            )
85        }
86    }
87
88    #[doc(alias = "gst_buffer_list_get")]
89    pub fn get(&self, idx: usize) -> Option<&BufferRef> {
90        unsafe {
91            if idx >= self.len() {
92                return None;
93            }
94            let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
95            Some(BufferRef::from_ptr(ptr))
96        }
97    }
98
99    #[doc(alias = "gst_buffer_list_get")]
100    pub fn get_owned(&self, idx: usize) -> Option<Buffer> {
101        unsafe {
102            if idx >= self.len() {
103                return None;
104            }
105            let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
106            Some(from_glib_none(ptr))
107        }
108    }
109
110    #[doc(alias = "gst_buffer_list_get_writable")]
111    #[doc(alias = "get_writable")]
112    pub fn get_mut(&mut self, idx: usize) -> Option<&mut BufferRef> {
113        unsafe {
114            if idx >= self.len() {
115                return None;
116            }
117            let ptr = ffi::gst_buffer_list_get_writable(self.as_mut_ptr(), idx as u32);
118            Some(BufferRef::from_mut_ptr(ptr))
119        }
120    }
121
122    #[doc(alias = "gst_buffer_list_length")]
123    pub fn len(&self) -> usize {
124        unsafe { ffi::gst_buffer_list_length(self.as_mut_ptr()) as usize }
125    }
126
127    #[doc(alias = "gst_buffer_list_calculate_size")]
128    pub fn calculate_size(&self) -> usize {
129        unsafe { ffi::gst_buffer_list_calculate_size(self.as_mut_ptr()) }
130    }
131
132    pub fn is_empty(&self) -> bool {
133        self.len() == 0
134    }
135
136    pub fn iter(&self) -> Iter<'_> {
137        Iter::new(self)
138    }
139
140    pub fn iter_owned(&self) -> IterOwned<'_> {
141        IterOwned::new(self)
142    }
143
144    #[doc(alias = "gst_buffer_list_foreach")]
145    pub fn foreach<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(&self, func: F) {
146        unsafe extern "C" fn trampoline<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(
147            buffer: *mut *mut ffi::GstBuffer,
148            idx: u32,
149            user_data: glib::ffi::gpointer,
150        ) -> glib::ffi::gboolean {
151            unsafe {
152                let func = user_data as *mut F;
153                let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx as usize);
154
155                matches!(res, ControlFlow::Continue(_)).into_glib()
156            }
157        }
158
159        unsafe {
160            let mut func = func;
161            let func_ptr: &mut F = &mut func;
162
163            let _ = ffi::gst_buffer_list_foreach(
164                self.as_ptr() as *mut _,
165                Some(trampoline::<F>),
166                func_ptr as *mut _ as *mut _,
167            );
168        }
169    }
170
171    #[doc(alias = "gst_buffer_list_foreach")]
172    pub fn foreach_mut<F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
173        &mut self,
174        func: F,
175    ) {
176        unsafe extern "C" fn trampoline<
177            F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
178        >(
179            buffer: *mut *mut ffi::GstBuffer,
180            idx: u32,
181            user_data: glib::ffi::gpointer,
182        ) -> glib::ffi::gboolean {
183            unsafe {
184                let func = user_data as *mut F;
185                let res = (*func)(
186                    Buffer::from_glib_full(ptr::replace(
187                        buffer as *mut *const ffi::GstBuffer,
188                        ptr::null_mut::<ffi::GstBuffer>(),
189                    )),
190                    idx as usize,
191                );
192
193                let (cont, res_buffer) = match res {
194                    ControlFlow::Continue(res_buffer) => (true, res_buffer),
195                    ControlFlow::Break(res_buffer) => (false, res_buffer),
196                };
197
198                match res_buffer {
199                    None => {
200                        *buffer = ptr::null_mut();
201                    }
202                    Some(new_buffer) => {
203                        *buffer = new_buffer.into_glib_ptr();
204                    }
205                }
206
207                cont.into_glib()
208            }
209        }
210
211        unsafe {
212            let mut func = func;
213            let func_ptr: &mut F = &mut func;
214
215            let _ = ffi::gst_buffer_list_foreach(
216                self.as_ptr() as *mut _,
217                Some(trampoline::<F>),
218                func_ptr as *mut _ as *mut _,
219            );
220        }
221    }
222
223    pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<'_> {
224        let (start_idx, end_idx) = self.buffer_range_to_start_end_idx(range);
225        Drain {
226            list: self,
227            start_idx,
228            end_idx,
229        }
230    }
231}
232
233impl Default for BufferList {
234    fn default() -> Self {
235        Self::new()
236    }
237}
238
239impl fmt::Debug for BufferList {
240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241        BufferListRef::fmt(self, f)
242    }
243}
244
245impl fmt::Debug for BufferListRef {
246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247        use crate::{ClockTime, utils::Displayable};
248
249        let size = self.iter().map(|b| b.size()).sum::<usize>();
250        let (pts, dts) = self
251            .get(0)
252            .map(|b| (b.pts(), b.dts()))
253            .unwrap_or((ClockTime::NONE, ClockTime::NONE));
254
255        f.debug_struct("BufferList")
256            .field("ptr", &self.as_ptr())
257            .field("buffers", &self.len())
258            .field("pts", &pts.display())
259            .field("dts", &dts.display())
260            .field("size", &size)
261            .finish()
262    }
263}
264
265macro_rules! define_iter(
266    ($name:ident, $styp:ty, $get_item:expr) => {
267        crate::utils::define_fixed_size_iter!(
268            $name, &'a BufferListRef, $styp,
269            |collection: &BufferListRef| collection.len(),
270            $get_item
271        );
272    }
273);
274
275define_iter!(Iter, &'a BufferRef, |list: &BufferListRef, idx| unsafe {
276    let ptr = ffi::gst_buffer_list_get(list.as_mut_ptr(), idx as u32);
277    BufferRef::from_ptr(ptr)
278});
279
280define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| unsafe {
281    let ptr = ffi::gst_buffer_list_get(list.as_mut_ptr(), idx as u32);
282    from_glib_none(ptr)
283});
284
285#[derive(Debug)]
286pub struct Drain<'a> {
287    list: &'a mut BufferListRef,
288    start_idx: usize,
289    end_idx: usize,
290}
291
292impl Iterator for Drain<'_> {
293    type Item = Buffer;
294
295    #[inline]
296    fn next(&mut self) -> Option<Self::Item> {
297        if self.start_idx >= self.end_idx {
298            return None;
299        }
300
301        let buffer = unsafe {
302            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
303                self.list.as_mut_ptr(),
304                self.start_idx as u32,
305            ));
306            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.start_idx as u32, 1);
307            buffer
308        };
309
310        self.end_idx -= 1;
311
312        Some(buffer)
313    }
314
315    #[inline]
316    fn size_hint(&self) -> (usize, Option<usize>) {
317        let remaining = self.end_idx - self.start_idx;
318
319        (remaining, Some(remaining))
320    }
321
322    #[inline]
323    fn count(self) -> usize {
324        self.end_idx - self.start_idx
325    }
326
327    #[inline]
328    fn nth(&mut self, n: usize) -> Option<Self::Item> {
329        let (end, overflow) = self.start_idx.overflowing_add(n);
330        if end >= self.end_idx || overflow {
331            unsafe {
332                ffi::gst_buffer_list_remove(
333                    self.list.as_mut_ptr(),
334                    self.start_idx as u32,
335                    (self.end_idx - self.start_idx) as u32,
336                );
337            }
338            self.start_idx = self.end_idx;
339            None
340        } else {
341            let buffer = unsafe {
342                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
343                    self.list.as_mut_ptr(),
344                    end as u32,
345                ));
346                ffi::gst_buffer_list_remove(
347                    self.list.as_mut_ptr(),
348                    self.start_idx as u32,
349                    n as u32,
350                );
351                buffer
352            };
353            self.end_idx -= n;
354            Some(buffer)
355        }
356    }
357
358    #[inline]
359    fn last(mut self) -> Option<Self::Item> {
360        if self.start_idx == self.end_idx {
361            None
362        } else {
363            let buffer = unsafe {
364                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
365                    self.list.as_mut_ptr(),
366                    self.end_idx as u32 - 1,
367                ));
368                ffi::gst_buffer_list_remove(
369                    self.list.as_mut_ptr(),
370                    self.start_idx as u32,
371                    (self.end_idx - self.start_idx) as u32,
372                );
373                buffer
374            };
375            self.end_idx = self.start_idx;
376            Some(buffer)
377        }
378    }
379}
380
381impl DoubleEndedIterator for Drain<'_> {
382    #[inline]
383    fn next_back(&mut self) -> Option<Self::Item> {
384        if self.start_idx == self.end_idx {
385            return None;
386        }
387
388        self.end_idx -= 1;
389        let buffer = unsafe {
390            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
391                self.list.as_mut_ptr(),
392                self.end_idx as u32,
393            ));
394            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, 1);
395            buffer
396        };
397
398        Some(buffer)
399    }
400
401    #[inline]
402    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
403        let (end, overflow) = self.end_idx.overflowing_sub(n);
404        if end <= self.start_idx || overflow {
405            unsafe {
406                ffi::gst_buffer_list_remove(
407                    self.list.as_mut_ptr(),
408                    self.start_idx as u32,
409                    (self.end_idx - self.start_idx) as u32,
410                );
411            }
412            self.start_idx = self.end_idx;
413            None
414        } else {
415            self.end_idx = end - 1;
416            let buffer = unsafe {
417                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
418                    self.list.as_mut_ptr(),
419                    self.end_idx as u32,
420                ));
421                ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, n as u32);
422                buffer
423            };
424
425            Some(buffer)
426        }
427    }
428}
429
430impl ExactSizeIterator for Drain<'_> {}
431
432impl std::iter::FusedIterator for Drain<'_> {}
433
434impl Drop for Drain<'_> {
435    fn drop(&mut self) {
436        if self.start_idx >= self.end_idx {
437            return;
438        }
439
440        unsafe {
441            ffi::gst_buffer_list_remove(
442                self.list.as_mut_ptr(),
443                self.start_idx as u32,
444                (self.end_idx - self.start_idx) as u32,
445            );
446        }
447    }
448}
449
450impl<'a> IntoIterator for &'a BufferListRef {
451    type IntoIter = Iter<'a>;
452    type Item = &'a BufferRef;
453
454    fn into_iter(self) -> Self::IntoIter {
455        self.iter()
456    }
457}
458
459impl From<Buffer> for BufferList {
460    fn from(value: Buffer) -> Self {
461        skip_assert_initialized!();
462
463        let mut list = BufferList::new_sized(1);
464        {
465            let list = list.get_mut().unwrap();
466            list.add(value);
467        }
468        list
469    }
470}
471
472impl<const N: usize> From<[Buffer; N]> for BufferList {
473    fn from(value: [Buffer; N]) -> Self {
474        skip_assert_initialized!();
475
476        let mut list = BufferList::new_sized(N);
477        {
478            let list = list.get_mut().unwrap();
479            value.into_iter().for_each(|b| list.add(b));
480        }
481        list
482    }
483}
484
485impl std::iter::FromIterator<Buffer> for BufferList {
486    fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
487        assert_initialized_main_thread!();
488
489        let iter = iter.into_iter();
490
491        let mut list = BufferList::new_sized(iter.size_hint().0);
492
493        {
494            let list = list.get_mut().unwrap();
495            iter.for_each(|b| list.add(b));
496        }
497
498        list
499    }
500}
501
502impl std::iter::Extend<Buffer> for BufferListRef {
503    fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
504        iter.into_iter().for_each(|b| self.add(b));
505    }
506}
507
508#[cfg(test)]
509mod tests {
510    use super::*;
511    use crate::ClockTime;
512
513    fn make_buffer_list(size: usize) -> BufferList {
514        skip_assert_initialized!();
515
516        let mut buffer_list = BufferList::new();
517        {
518            let buffer_list = buffer_list.get_mut().unwrap();
519            for i in 0..size {
520                let mut buffer = Buffer::new();
521                buffer
522                    .get_mut()
523                    .unwrap()
524                    .set_pts(ClockTime::SECOND * i as u64);
525                buffer_list.add(buffer);
526            }
527        }
528        buffer_list
529    }
530
531    #[test]
532    fn test_foreach() {
533        crate::init().unwrap();
534
535        let buffer_list = make_buffer_list(2);
536
537        let mut res = vec![];
538        buffer_list.foreach(|buffer, idx| {
539            res.push((buffer.pts(), idx));
540            ControlFlow::Continue(())
541        });
542
543        assert_eq!(
544            res,
545            &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
546        );
547    }
548
549    #[test]
550    fn test_foreach_mut() {
551        crate::init().unwrap();
552
553        let mut buffer_list = make_buffer_list(3);
554
555        let mut res = vec![];
556        buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
557            res.push((buffer.pts(), idx));
558
559            if let Some(ClockTime::ZERO) = buffer.pts() {
560                ControlFlow::Continue(Some(buffer))
561            } else if let Some(ClockTime::SECOND) = buffer.pts() {
562                ControlFlow::Continue(None)
563            } else {
564                let mut new_buffer = Buffer::new();
565                new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
566                ControlFlow::Continue(Some(new_buffer))
567            }
568        });
569
570        assert_eq!(
571            res,
572            &[
573                (Some(ClockTime::ZERO), 0),
574                (Some(ClockTime::SECOND), 1),
575                (Some(2 * ClockTime::SECOND), 1)
576            ]
577        );
578
579        let mut res = vec![];
580        buffer_list.foreach(|buffer, idx| {
581            res.push((buffer.pts(), idx));
582            ControlFlow::Continue(())
583        });
584
585        assert_eq!(
586            res,
587            &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
588        );
589
590        // Try removing buffers from inside foreach_mut
591        let mut buffer_list = BufferList::new();
592        for i in 0..10 {
593            let buffer_list = buffer_list.get_mut().unwrap();
594            let mut buffer = Buffer::new();
595            buffer.get_mut().unwrap().set_pts(i * ClockTime::SECOND);
596            buffer_list.add(buffer);
597        }
598
599        assert_eq!(buffer_list.len(), 10);
600
601        let buffer_list_ref = buffer_list.make_mut();
602
603        buffer_list_ref.foreach_mut(|buf, _n| {
604            let keep_packet = !(buf.pts().unwrap() / ClockTime::SECOND).is_multiple_of(3);
605            ControlFlow::Continue(keep_packet.then_some(buf))
606        });
607
608        assert_eq!(buffer_list.len(), 6);
609
610        let res = buffer_list
611            .iter()
612            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
613            .collect::<Vec<_>>();
614
615        assert_eq!(res, &[1, 2, 4, 5, 7, 8]);
616    }
617
618    #[test]
619    fn test_remove() {
620        crate::init().unwrap();
621
622        let mut buffer_list = make_buffer_list(10);
623
624        buffer_list.make_mut().remove(0..2);
625
626        let buffers_left = buffer_list
627            .iter()
628            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
629            .collect::<Vec<_>>();
630
631        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
632
633        buffer_list.make_mut().remove(0..=2);
634
635        let buffers_left = buffer_list
636            .iter()
637            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
638            .collect::<Vec<_>>();
639
640        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
641
642        buffer_list.make_mut().remove(2..);
643
644        let buffers_left = buffer_list
645            .iter()
646            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
647            .collect::<Vec<_>>();
648
649        assert_eq!(buffers_left, &[5, 6]);
650
651        buffer_list.make_mut().remove(..);
652
653        assert!(buffer_list.is_empty());
654    }
655
656    #[test]
657    fn test_drain() {
658        crate::init().unwrap();
659
660        let mut buffer_list = make_buffer_list(10);
661
662        let buffers_removed = buffer_list
663            .make_mut()
664            .drain(0..2)
665            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
666            .collect::<Vec<_>>();
667
668        assert_eq!(buffers_removed, &[0, 1]);
669
670        let buffers_left = buffer_list
671            .iter()
672            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
673            .collect::<Vec<_>>();
674
675        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
676
677        let buffers_removed = buffer_list
678            .make_mut()
679            .drain(0..=2)
680            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
681            .collect::<Vec<_>>();
682
683        assert_eq!(buffers_removed, &[2, 3, 4]);
684
685        let buffers_left = buffer_list
686            .iter()
687            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
688            .collect::<Vec<_>>();
689
690        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
691
692        let buffers_removed = buffer_list
693            .make_mut()
694            .drain(2..)
695            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
696            .collect::<Vec<_>>();
697
698        assert_eq!(buffers_removed, &[7, 8, 9]);
699
700        let buffers_left = buffer_list
701            .iter()
702            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
703            .collect::<Vec<_>>();
704
705        assert_eq!(buffers_left, &[5, 6]);
706
707        let buffers_removed = buffer_list
708            .make_mut()
709            .drain(..)
710            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
711            .collect::<Vec<_>>();
712
713        assert_eq!(buffers_removed, &[5, 6]);
714
715        assert!(buffer_list.is_empty());
716    }
717
718    #[test]
719    fn test_drain_drop() {
720        crate::init().unwrap();
721
722        let mut buffer_list = make_buffer_list(10);
723
724        buffer_list.make_mut().drain(0..2);
725
726        let buffers_left = buffer_list
727            .iter()
728            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
729            .collect::<Vec<_>>();
730
731        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
732
733        buffer_list.make_mut().drain(0..=2);
734
735        let buffers_left = buffer_list
736            .iter()
737            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
738            .collect::<Vec<_>>();
739
740        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
741
742        buffer_list.make_mut().drain(2..);
743
744        let buffers_left = buffer_list
745            .iter()
746            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
747            .collect::<Vec<_>>();
748
749        assert_eq!(buffers_left, &[5, 6]);
750
751        buffer_list.make_mut().drain(..);
752
753        assert!(buffer_list.is_empty());
754    }
755}