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