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