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 #[doc(alias = "gst_buffer_list_remove")]
68 pub fn remove(&mut self, range: impl RangeBounds<usize>) {
69 let n = self.len();
70 debug_assert!(n <= u32::MAX as usize);
71
72 let start_idx = match range.start_bound() {
73 std::ops::Bound::Included(idx) => *idx,
74 std::ops::Bound::Excluded(idx) => idx.checked_add(1).unwrap(),
75 std::ops::Bound::Unbounded => 0,
76 };
77 assert!(start_idx < n);
78
79 let end_idx = match range.end_bound() {
80 std::ops::Bound::Included(idx) => idx.checked_add(1).unwrap(),
81 std::ops::Bound::Excluded(idx) => *idx,
82 std::ops::Bound::Unbounded => n,
83 };
84 assert!(end_idx <= n);
85
86 unsafe {
87 ffi::gst_buffer_list_remove(
88 self.as_mut_ptr(),
89 start_idx as u32,
90 (end_idx - start_idx) as u32,
91 )
92 }
93 }
94
95 #[doc(alias = "gst_buffer_list_get")]
96 pub fn get(&self, idx: usize) -> Option<&BufferRef> {
97 unsafe {
98 if idx >= self.len() {
99 return None;
100 }
101 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
102 Some(BufferRef::from_ptr(ptr))
103 }
104 }
105
106 #[doc(alias = "gst_buffer_list_get")]
107 pub fn get_owned(&self, idx: usize) -> Option<Buffer> {
108 unsafe {
109 if idx >= self.len() {
110 return None;
111 }
112 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx as u32);
113 Some(from_glib_none(ptr))
114 }
115 }
116
117 #[doc(alias = "gst_buffer_list_get_writable")]
118 #[doc(alias = "get_writable")]
119 pub fn get_mut(&mut self, idx: usize) -> Option<&mut BufferRef> {
120 unsafe {
121 if idx >= self.len() {
122 return None;
123 }
124 let ptr = ffi::gst_buffer_list_get_writable(self.as_mut_ptr(), idx as u32);
125 Some(BufferRef::from_mut_ptr(ptr))
126 }
127 }
128
129 #[doc(alias = "gst_buffer_list_length")]
130 pub fn len(&self) -> usize {
131 unsafe { ffi::gst_buffer_list_length(self.as_mut_ptr()) as usize }
132 }
133
134 #[doc(alias = "gst_buffer_list_calculate_size")]
135 pub fn calculate_size(&self) -> usize {
136 unsafe { ffi::gst_buffer_list_calculate_size(self.as_mut_ptr()) }
137 }
138
139 pub fn is_empty(&self) -> bool {
140 self.len() == 0
141 }
142
143 pub fn iter(&self) -> Iter {
144 Iter::new(self)
145 }
146
147 pub fn iter_owned(&self) -> IterOwned {
148 IterOwned::new(self)
149 }
150
151 #[doc(alias = "gst_buffer_list_foreach")]
152 pub fn foreach<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(&self, func: F) -> bool {
153 unsafe extern "C" fn trampoline<F: FnMut(&Buffer, usize) -> ControlFlow<(), ()>>(
154 buffer: *mut *mut ffi::GstBuffer,
155 idx: u32,
156 user_data: glib::ffi::gpointer,
157 ) -> glib::ffi::gboolean {
158 let func = user_data as *mut F;
159 let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx as usize);
160
161 matches!(res, ControlFlow::Continue(_)).into_glib()
162 }
163
164 unsafe {
165 let mut func = func;
166 let func_ptr: &mut F = &mut func;
167
168 from_glib(ffi::gst_buffer_list_foreach(
169 self.as_ptr() as *mut _,
170 Some(trampoline::<F>),
171 func_ptr as *mut _ as *mut _,
172 ))
173 }
174 }
175
176 #[doc(alias = "gst_buffer_list_foreach")]
177 pub fn foreach_mut<F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
178 &mut self,
179 func: F,
180 ) -> bool {
181 unsafe extern "C" fn trampoline<
182 F: FnMut(Buffer, usize) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
183 >(
184 buffer: *mut *mut ffi::GstBuffer,
185 idx: u32,
186 user_data: glib::ffi::gpointer,
187 ) -> glib::ffi::gboolean {
188 let func = user_data as *mut F;
189 let res = (*func)(
190 Buffer::from_glib_full(ptr::replace(
191 buffer as *mut *const ffi::GstBuffer,
192 ptr::null_mut::<ffi::GstBuffer>(),
193 )),
194 idx as usize,
195 );
196
197 let (cont, res_buffer) = match res {
198 ControlFlow::Continue(res_buffer) => (true, res_buffer),
199 ControlFlow::Break(res_buffer) => (false, res_buffer),
200 };
201
202 match res_buffer {
203 None => {
204 *buffer = ptr::null_mut();
205 }
206 Some(new_buffer) => {
207 *buffer = new_buffer.into_glib_ptr();
208 }
209 }
210
211 cont.into_glib()
212 }
213
214 unsafe {
215 let mut func = func;
216 let func_ptr: &mut F = &mut func;
217
218 from_glib(ffi::gst_buffer_list_foreach(
219 self.as_ptr() as *mut _,
220 Some(trampoline::<F>),
221 func_ptr as *mut _ as *mut _,
222 ))
223 }
224 }
225}
226
227impl Default for BufferList {
228 fn default() -> Self {
229 Self::new()
230 }
231}
232
233impl fmt::Debug for BufferList {
234 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
235 BufferListRef::fmt(self, f)
236 }
237}
238
239impl fmt::Debug for BufferListRef {
240 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241 use crate::{utils::Displayable, ClockTime};
242
243 let size = self.iter().map(|b| b.size()).sum::<usize>();
244 let (pts, dts) = self
245 .get(0)
246 .map(|b| (b.pts(), b.dts()))
247 .unwrap_or((ClockTime::NONE, ClockTime::NONE));
248
249 f.debug_struct("BufferList")
250 .field("ptr", &self.as_ptr())
251 .field("buffers", &self.len())
252 .field("pts", &pts.display())
253 .field("dts", &dts.display())
254 .field("size", &size)
255 .finish()
256 }
257}
258
259macro_rules! define_iter(
260 ($name:ident, $styp:ty, $get_item:expr) => {
261 #[derive(Debug)]
262 pub struct $name<'a> {
263 list: &'a BufferListRef,
264 idx: usize,
265 size: usize,
266 }
267
268 impl<'a> $name<'a> {
269 fn new(list: &'a BufferListRef) -> $name<'a> {
270 skip_assert_initialized!();
271 $name {
272 list,
273 idx: 0,
274 size: list.len(),
275 }
276 }
277 }
278
279 #[allow(clippy::redundant_closure_call)]
280 impl<'a> Iterator for $name<'a> {
281 type Item = $styp;
282
283 fn next(&mut self) -> Option<Self::Item> {
284 if self.idx >= self.size {
285 return None;
286 }
287
288 let item = $get_item(self.list, self.idx).unwrap();
289 self.idx += 1;
290
291 Some(item)
292 }
293
294 fn size_hint(&self) -> (usize, Option<usize>) {
295 let remaining = self.size - self.idx;
296
297 (remaining, Some(remaining))
298 }
299
300 fn count(self) -> usize {
301 self.size - self.idx
302 }
303
304 fn nth(&mut self, n: usize) -> Option<Self::Item> {
305 let (end, overflow) = self.idx.overflowing_add(n);
306 if end >= self.size || overflow {
307 self.idx = self.size;
308 None
309 } else {
310 self.idx = end + 1;
311 Some($get_item(self.list, end).unwrap())
312 }
313 }
314
315 fn last(self) -> Option<Self::Item> {
316 if self.idx == self.size {
317 None
318 } else {
319 Some($get_item(self.list, self.size - 1).unwrap())
320 }
321 }
322 }
323
324 #[allow(clippy::redundant_closure_call)]
325 impl<'a> DoubleEndedIterator for $name<'a> {
326 fn next_back(&mut self) -> Option<Self::Item> {
327 if self.idx == self.size {
328 return None;
329 }
330
331 self.size -= 1;
332 Some($get_item(self.list, self.size).unwrap())
333 }
334
335 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
336 let (end, overflow) = self.size.overflowing_sub(n);
337 if end <= self.idx || overflow {
338 self.idx = self.size;
339 None
340 } else {
341 self.size = end - 1;
342 Some($get_item(self.list, self.size).unwrap())
343 }
344 }
345 }
346
347 impl<'a> ExactSizeIterator for $name<'a> {}
348 impl<'a> std::iter::FusedIterator for $name<'a> {}
349 }
350);
351
352define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
353 list.get(idx)
354});
355
356define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
357 list.get_owned(idx)
358});
359
360impl<'a> IntoIterator for &'a BufferListRef {
361 type IntoIter = Iter<'a>;
362 type Item = &'a BufferRef;
363
364 fn into_iter(self) -> Self::IntoIter {
365 self.iter()
366 }
367}
368
369impl From<Buffer> for BufferList {
370 fn from(value: Buffer) -> Self {
371 skip_assert_initialized!();
372
373 let mut list = BufferList::new_sized(1);
374 {
375 let list = list.get_mut().unwrap();
376 list.add(value);
377 }
378 list
379 }
380}
381
382impl<const N: usize> From<[Buffer; N]> for BufferList {
383 fn from(value: [Buffer; N]) -> Self {
384 skip_assert_initialized!();
385
386 let mut list = BufferList::new_sized(N);
387 {
388 let list = list.get_mut().unwrap();
389 value.into_iter().for_each(|b| list.add(b));
390 }
391 list
392 }
393}
394
395impl std::iter::FromIterator<Buffer> for BufferList {
396 fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
397 assert_initialized_main_thread!();
398
399 let iter = iter.into_iter();
400
401 let mut list = BufferList::new_sized(iter.size_hint().0);
402
403 {
404 let list = list.get_mut().unwrap();
405 iter.for_each(|b| list.add(b));
406 }
407
408 list
409 }
410}
411
412impl std::iter::Extend<Buffer> for BufferListRef {
413 fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
414 iter.into_iter().for_each(|b| self.add(b));
415 }
416}
417
418#[cfg(test)]
419mod tests {
420 use super::*;
421 use crate::ClockTime;
422
423 fn make_buffer_list(size: usize) -> BufferList {
424 skip_assert_initialized!();
425
426 let mut buffer_list = BufferList::new();
427 {
428 let buffer_list = buffer_list.get_mut().unwrap();
429 for i in 0..size {
430 let mut buffer = Buffer::new();
431 buffer
432 .get_mut()
433 .unwrap()
434 .set_pts(ClockTime::SECOND * i as u64);
435 buffer_list.add(buffer);
436 }
437 }
438 buffer_list
439 }
440
441 #[test]
442 fn test_foreach() {
443 crate::init().unwrap();
444
445 let buffer_list = make_buffer_list(2);
446
447 let mut res = vec![];
448 buffer_list.foreach(|buffer, idx| {
449 res.push((buffer.pts(), idx));
450 ControlFlow::Continue(())
451 });
452
453 assert_eq!(
454 res,
455 &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
456 );
457 }
458
459 #[test]
460 fn test_foreach_mut() {
461 crate::init().unwrap();
462
463 let mut buffer_list = make_buffer_list(3);
464
465 let mut res = vec![];
466 buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
467 res.push((buffer.pts(), idx));
468
469 if let Some(ClockTime::ZERO) = buffer.pts() {
470 ControlFlow::Continue(Some(buffer))
471 } else if let Some(ClockTime::SECOND) = buffer.pts() {
472 ControlFlow::Continue(None)
473 } else {
474 let mut new_buffer = Buffer::new();
475 new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
476 ControlFlow::Continue(Some(new_buffer))
477 }
478 });
479
480 assert_eq!(
481 res,
482 &[
483 (Some(ClockTime::ZERO), 0),
484 (Some(ClockTime::SECOND), 1),
485 (Some(2 * ClockTime::SECOND), 1)
486 ]
487 );
488
489 let mut res = vec![];
490 buffer_list.foreach(|buffer, idx| {
491 res.push((buffer.pts(), idx));
492 ControlFlow::Continue(())
493 });
494
495 assert_eq!(
496 res,
497 &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
498 );
499
500 let mut buffer_list = BufferList::new();
502 for i in 0..10 {
503 let buffer_list = buffer_list.get_mut().unwrap();
504 let mut buffer = Buffer::new();
505 buffer.get_mut().unwrap().set_pts(i * ClockTime::SECOND);
506 buffer_list.add(buffer);
507 }
508
509 assert_eq!(buffer_list.len(), 10);
510
511 let buffer_list_ref = buffer_list.make_mut();
512
513 buffer_list_ref.foreach_mut(|buf, _n| {
514 let keep_packet = (buf.pts().unwrap() / ClockTime::SECOND) % 3 != 0;
515 ControlFlow::Continue(keep_packet.then_some(buf))
516 });
517
518 assert_eq!(buffer_list.len(), 6);
519
520 let res = buffer_list
521 .iter()
522 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
523 .collect::<Vec<_>>();
524
525 assert_eq!(res, &[1, 2, 4, 5, 7, 8]);
526 }
527
528 #[test]
529 fn test_remove() {
530 crate::init().unwrap();
531
532 let mut buffer_list = make_buffer_list(10);
533
534 buffer_list.make_mut().remove(0..2);
535
536 let buffers_left = buffer_list
537 .iter()
538 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
539 .collect::<Vec<_>>();
540
541 assert_eq!(buffers_left, &[2, 3, 4, 5, 6, 7, 8, 9]);
542
543 buffer_list.make_mut().remove(0..=2);
544
545 let buffers_left = buffer_list
546 .iter()
547 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
548 .collect::<Vec<_>>();
549
550 assert_eq!(buffers_left, &[5, 6, 7, 8, 9]);
551
552 buffer_list.make_mut().remove(2..);
553
554 let buffers_left = buffer_list
555 .iter()
556 .map(|buf| buf.pts().unwrap() / ClockTime::SECOND)
557 .collect::<Vec<_>>();
558
559 assert_eq!(buffers_left, &[5, 6]);
560
561 buffer_list.make_mut().remove(..);
562
563 assert!(buffer_list.is_empty());
564 }
565}