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