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