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")]
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 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}