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) -> bool {
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            from_glib(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    ) -> bool {
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            from_glib(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    #[derive(Debug)]
264    pub struct $name<'a> {
265        list: &'a BufferListRef,
266        idx: usize,
267        size: usize,
268    }
269
270    impl<'a> $name<'a> {
271        fn new(list: &'a BufferListRef) -> $name<'a> {
272            skip_assert_initialized!();
273            $name {
274                list,
275                idx: 0,
276                size: list.len(),
277            }
278        }
279    }
280
281    #[allow(clippy::redundant_closure_call)]
282    impl<'a> Iterator for $name<'a> {
283        type Item = $styp;
284
285        fn next(&mut self) -> Option<Self::Item> {
286            if self.idx >= self.size {
287                return None;
288            }
289
290            let item = $get_item(self.list, self.idx).unwrap();
291            self.idx += 1;
292
293            Some(item)
294        }
295
296        fn size_hint(&self) -> (usize, Option<usize>) {
297            let remaining = self.size - self.idx;
298
299            (remaining, Some(remaining))
300        }
301
302        fn count(self) -> usize {
303            self.size - self.idx
304        }
305
306        fn nth(&mut self, n: usize) -> Option<Self::Item> {
307            let (end, overflow) = self.idx.overflowing_add(n);
308            if end >= self.size || overflow {
309                self.idx = self.size;
310                None
311            } else {
312                self.idx = end + 1;
313                Some($get_item(self.list, end).unwrap())
314            }
315        }
316
317        fn last(self) -> Option<Self::Item> {
318            if self.idx == self.size {
319                None
320            } else {
321                Some($get_item(self.list, self.size - 1).unwrap())
322            }
323        }
324    }
325
326    #[allow(clippy::redundant_closure_call)]
327    impl<'a> DoubleEndedIterator for $name<'a> {
328        fn next_back(&mut self) -> Option<Self::Item> {
329            if self.idx == self.size {
330                return None;
331            }
332
333            self.size -= 1;
334            Some($get_item(self.list, self.size).unwrap())
335        }
336
337        fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
338            let (end, overflow) = self.size.overflowing_sub(n);
339            if end <= self.idx || overflow {
340                self.idx = self.size;
341                None
342            } else {
343                self.size = end - 1;
344                Some($get_item(self.list, self.size).unwrap())
345            }
346        }
347    }
348
349    impl<'a> ExactSizeIterator for $name<'a> {}
350    impl<'a> std::iter::FusedIterator for $name<'a> {}
351    }
352);
353
354define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
355    list.get(idx)
356});
357
358define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
359    list.get_owned(idx)
360});
361
362#[derive(Debug)]
363pub struct Drain<'a> {
364    list: &'a mut BufferListRef,
365    start_idx: usize,
366    end_idx: usize,
367}
368
369impl Iterator for Drain<'_> {
370    type Item = Buffer;
371
372    #[inline]
373    fn next(&mut self) -> Option<Self::Item> {
374        if self.start_idx >= self.end_idx {
375            return None;
376        }
377
378        let buffer = unsafe {
379            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
380                self.list.as_mut_ptr(),
381                self.start_idx as u32,
382            ));
383            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.start_idx as u32, 1);
384            buffer
385        };
386
387        self.end_idx -= 1;
388
389        Some(buffer)
390    }
391
392    #[inline]
393    fn size_hint(&self) -> (usize, Option<usize>) {
394        let remaining = self.end_idx - self.start_idx;
395
396        (remaining, Some(remaining))
397    }
398
399    #[inline]
400    fn count(self) -> usize {
401        self.end_idx - self.start_idx
402    }
403
404    #[inline]
405    fn nth(&mut self, n: usize) -> Option<Self::Item> {
406        let (end, overflow) = self.start_idx.overflowing_add(n);
407        if end >= self.end_idx || overflow {
408            unsafe {
409                ffi::gst_buffer_list_remove(
410                    self.list.as_mut_ptr(),
411                    self.start_idx as u32,
412                    (self.end_idx - self.start_idx) as u32,
413                );
414            }
415            self.start_idx = self.end_idx;
416            None
417        } else {
418            let buffer = unsafe {
419                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
420                    self.list.as_mut_ptr(),
421                    end as u32,
422                ));
423                ffi::gst_buffer_list_remove(
424                    self.list.as_mut_ptr(),
425                    self.start_idx as u32,
426                    n as u32,
427                );
428                buffer
429            };
430            self.end_idx -= n;
431            Some(buffer)
432        }
433    }
434
435    #[inline]
436    fn last(mut self) -> Option<Self::Item> {
437        if self.start_idx == self.end_idx {
438            None
439        } else {
440            let buffer = unsafe {
441                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
442                    self.list.as_mut_ptr(),
443                    self.end_idx as u32 - 1,
444                ));
445                ffi::gst_buffer_list_remove(
446                    self.list.as_mut_ptr(),
447                    self.start_idx as u32,
448                    (self.end_idx - self.start_idx) as u32,
449                );
450                buffer
451            };
452            self.end_idx = self.start_idx;
453            Some(buffer)
454        }
455    }
456}
457
458impl DoubleEndedIterator for Drain<'_> {
459    #[inline]
460    fn next_back(&mut self) -> Option<Self::Item> {
461        if self.start_idx == self.end_idx {
462            return None;
463        }
464
465        self.end_idx -= 1;
466        let buffer = unsafe {
467            let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
468                self.list.as_mut_ptr(),
469                self.end_idx as u32,
470            ));
471            ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, 1);
472            buffer
473        };
474
475        Some(buffer)
476    }
477
478    #[inline]
479    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
480        let (end, overflow) = self.end_idx.overflowing_sub(n);
481        if end <= self.start_idx || overflow {
482            unsafe {
483                ffi::gst_buffer_list_remove(
484                    self.list.as_mut_ptr(),
485                    self.start_idx as u32,
486                    (self.end_idx - self.start_idx) as u32,
487                );
488            }
489            self.start_idx = self.end_idx;
490            None
491        } else {
492            self.end_idx = end - 1;
493            let buffer = unsafe {
494                let buffer = Buffer::from_glib_none(ffi::gst_buffer_list_get(
495                    self.list.as_mut_ptr(),
496                    self.end_idx as u32,
497                ));
498                ffi::gst_buffer_list_remove(self.list.as_mut_ptr(), self.end_idx as u32, n as u32);
499                buffer
500            };
501
502            Some(buffer)
503        }
504    }
505}
506
507impl ExactSizeIterator for Drain<'_> {}
508
509impl std::iter::FusedIterator for Drain<'_> {}
510
511impl Drop for Drain<'_> {
512    fn drop(&mut self) {
513        if self.start_idx >= self.end_idx {
514            return;
515        }
516
517        unsafe {
518            ffi::gst_buffer_list_remove(
519                self.list.as_mut_ptr(),
520                self.start_idx as u32,
521                (self.end_idx - self.start_idx) as u32,
522            );
523        }
524    }
525}
526
527impl<'a> IntoIterator for &'a BufferListRef {
528    type IntoIter = Iter<'a>;
529    type Item = &'a BufferRef;
530
531    fn into_iter(self) -> Self::IntoIter {
532        self.iter()
533    }
534}
535
536impl From<Buffer> for BufferList {
537    fn from(value: Buffer) -> Self {
538        skip_assert_initialized!();
539
540        let mut list = BufferList::new_sized(1);
541        {
542            let list = list.get_mut().unwrap();
543            list.add(value);
544        }
545        list
546    }
547}
548
549impl<const N: usize> From<[Buffer; N]> for BufferList {
550    fn from(value: [Buffer; N]) -> Self {
551        skip_assert_initialized!();
552
553        let mut list = BufferList::new_sized(N);
554        {
555            let list = list.get_mut().unwrap();
556            value.into_iter().for_each(|b| list.add(b));
557        }
558        list
559    }
560}
561
562impl std::iter::FromIterator<Buffer> for BufferList {
563    fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
564        assert_initialized_main_thread!();
565
566        let iter = iter.into_iter();
567
568        let mut list = BufferList::new_sized(iter.size_hint().0);
569
570        {
571            let list = list.get_mut().unwrap();
572            iter.for_each(|b| list.add(b));
573        }
574
575        list
576    }
577}
578
579impl std::iter::Extend<Buffer> for BufferListRef {
580    fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
581        iter.into_iter().for_each(|b| self.add(b));
582    }
583}
584
585#[cfg(test)]
586mod tests {
587    use super::*;
588    use crate::ClockTime;
589
590    fn make_buffer_list(size: usize) -> BufferList {
591        skip_assert_initialized!();
592
593        let mut buffer_list = BufferList::new();
594        {
595            let buffer_list = buffer_list.get_mut().unwrap();
596            for i in 0..size {
597                let mut buffer = Buffer::new();
598                buffer
599                    .get_mut()
600                    .unwrap()
601                    .set_pts(ClockTime::SECOND * i as u64);
602                buffer_list.add(buffer);
603            }
604        }
605        buffer_list
606    }
607
608    #[test]
609    fn test_foreach() {
610        crate::init().unwrap();
611
612        let buffer_list = make_buffer_list(2);
613
614        let mut res = vec![];
615        buffer_list.foreach(|buffer, idx| {
616            res.push((buffer.pts(), idx));
617            ControlFlow::Continue(())
618        });
619
620        assert_eq!(
621            res,
622            &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
623        );
624    }
625
626    #[test]
627    fn test_foreach_mut() {
628        crate::init().unwrap();
629
630        let mut buffer_list = make_buffer_list(3);
631
632        let mut res = vec![];
633        buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
634            res.push((buffer.pts(), idx));
635
636            if let Some(ClockTime::ZERO) = buffer.pts() {
637                ControlFlow::Continue(Some(buffer))
638            } else if let Some(ClockTime::SECOND) = buffer.pts() {
639                ControlFlow::Continue(None)
640            } else {
641                let mut new_buffer = Buffer::new();
642                new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
643                ControlFlow::Continue(Some(new_buffer))
644            }
645        });
646
647        assert_eq!(
648            res,
649            &[
650                (Some(ClockTime::ZERO), 0),
651                (Some(ClockTime::SECOND), 1),
652                (Some(2 * ClockTime::SECOND), 1)
653            ]
654        );
655
656        let mut res = vec![];
657        buffer_list.foreach(|buffer, idx| {
658            res.push((buffer.pts(), idx));
659            ControlFlow::Continue(())
660        });
661
662        assert_eq!(
663            res,
664            &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
665        );
666
667        // Try removing buffers from inside foreach_mut
668        let mut buffer_list = BufferList::new();
669        for i in 0..10 {
670            let buffer_list = buffer_list.get_mut().unwrap();
671            let mut buffer = Buffer::new();
672            buffer.get_mut().unwrap().set_pts(i * ClockTime::SECOND);
673            buffer_list.add(buffer);
674        }
675
676        assert_eq!(buffer_list.len(), 10);
677
678        let buffer_list_ref = buffer_list.make_mut();
679
680        buffer_list_ref.foreach_mut(|buf, _n| {
681            let keep_packet = (buf.pts().unwrap() / ClockTime::SECOND) % 3 != 0;
682            ControlFlow::Continue(keep_packet.then_some(buf))
683        });
684
685        assert_eq!(buffer_list.len(), 6);
686
687        let res = buffer_list
688            .iter()
689            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
690            .collect::<Vec<_>>();
691
692        assert_eq!(res, &[1, 2, 4, 5, 7, 8]);
693    }
694
695    #[test]
696    fn test_remove() {
697        crate::init().unwrap();
698
699        let mut buffer_list = make_buffer_list(10);
700
701        buffer_list.make_mut().remove(0..2);
702
703        let buffers_left = buffer_list
704            .iter()
705            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
706            .collect::<Vec<_>>();
707
708        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
709
710        buffer_list.make_mut().remove(0..=2);
711
712        let buffers_left = buffer_list
713            .iter()
714            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
715            .collect::<Vec<_>>();
716
717        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
718
719        buffer_list.make_mut().remove(2..);
720
721        let buffers_left = buffer_list
722            .iter()
723            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
724            .collect::<Vec<_>>();
725
726        assert_eq!(buffers_left, &[5, 6]);
727
728        buffer_list.make_mut().remove(..);
729
730        assert!(buffer_list.is_empty());
731    }
732
733    #[test]
734    fn test_drain() {
735        crate::init().unwrap();
736
737        let mut buffer_list = make_buffer_list(10);
738
739        let buffers_removed = buffer_list
740            .make_mut()
741            .drain(0..2)
742            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
743            .collect::<Vec<_>>();
744
745        assert_eq!(buffers_removed, &[0, 1]);
746
747        let buffers_left = buffer_list
748            .iter()
749            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
750            .collect::<Vec<_>>();
751
752        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
753
754        let buffers_removed = buffer_list
755            .make_mut()
756            .drain(0..=2)
757            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
758            .collect::<Vec<_>>();
759
760        assert_eq!(buffers_removed, &[2, 3, 4]);
761
762        let buffers_left = buffer_list
763            .iter()
764            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
765            .collect::<Vec<_>>();
766
767        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
768
769        let buffers_removed = buffer_list
770            .make_mut()
771            .drain(2..)
772            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
773            .collect::<Vec<_>>();
774
775        assert_eq!(buffers_removed, &[7, 8, 9]);
776
777        let buffers_left = buffer_list
778            .iter()
779            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
780            .collect::<Vec<_>>();
781
782        assert_eq!(buffers_left, &[5, 6]);
783
784        let buffers_removed = buffer_list
785            .make_mut()
786            .drain(..)
787            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
788            .collect::<Vec<_>>();
789
790        assert_eq!(buffers_removed, &[5, 6]);
791
792        assert!(buffer_list.is_empty());
793    }
794
795    #[test]
796    fn test_drain_drop() {
797        crate::init().unwrap();
798
799        let mut buffer_list = make_buffer_list(10);
800
801        buffer_list.make_mut().drain(0..2);
802
803        let buffers_left = buffer_list
804            .iter()
805            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
806            .collect::<Vec<_>>();
807
808        assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
809
810        buffer_list.make_mut().drain(0..=2);
811
812        let buffers_left = buffer_list
813            .iter()
814            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
815            .collect::<Vec<_>>();
816
817        assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
818
819        buffer_list.make_mut().drain(2..);
820
821        let buffers_left = buffer_list
822            .iter()
823            .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
824            .collect::<Vec<_>>();
825
826        assert_eq!(buffers_left, &[5, 6]);
827
828        buffer_list.make_mut().drain(..);
829
830        assert!(buffer_list.is_empty());
831    }
832}