1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, ops::ControlFlow, ptr};
4
5use glib::translate::*;
6
7use crate::{Buffer, BufferRef};
8
9mini_object_wrapper!(BufferList, BufferListRef, ffi::GstBufferList, || {
10 ffi::gst_buffer_list_get_type()
11});
12
13impl BufferList {
14 #[doc(alias = "gst_buffer_list_new")]
15 pub fn new() -> Self {
16 assert_initialized_main_thread!();
17 unsafe { from_glib_full(ptr:ffi::gst_buffer_list_new()) }
18 }
19
20 #[doc(alias = "gst_buffer_list_new_sized")]
21 pub fn new_sized(size: usize) -> Self {
22 assert_initialized_main_thread!();
23 unsafe { from_glib_full(ptr:ffi::gst_buffer_list_new_sized(size as u32)) }
24 }
25}
26
27impl BufferListRef {
28 #[doc(alias = "gst_buffer_list_insert")]
29 pub fn insert(&mut self, idx: i32, buffer: Buffer) {
30 unsafe {
31 ffi::gst_buffer_list_insert(self.as_mut_ptr(), idx, buffer.into_glib_ptr());
32 }
33 }
34
35 #[doc(alias = "gst_buffer_list_add")]
36 pub fn add(&mut self, buffer: Buffer) {
37 self.insert(-1, buffer);
38 }
39
40 #[doc(alias = "gst_buffer_list_copy_deep")]
41 pub fn copy_deep(&self) -> BufferList {
42 unsafe { from_glib_full(ffi::gst_buffer_list_copy_deep(self.as_ptr())) }
43 }
44
45 #[doc(alias = "gst_buffer_list_remove")]
46 pub fn remove(&mut self, idx: u32, len: u32) {
47 unsafe { ffi::gst_buffer_list_remove(self.as_mut_ptr(), idx, len) }
48 }
49
50 #[doc(alias = "gst_buffer_list_get")]
51 pub fn get(&self, idx: u32) -> Option<&BufferRef> {
52 unsafe {
53 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx);
54 if ptr.is_null() {
55 None
56 } else {
57 Some(BufferRef::from_ptr(ptr))
58 }
59 }
60 }
61
62 #[doc(alias = "gst_buffer_list_get")]
63 pub fn get_owned(&self, idx: u32) -> Option<Buffer> {
64 unsafe {
65 let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx);
66 from_glib_none(ptr)
67 }
68 }
69
70 #[doc(alias = "gst_buffer_list_get_writable")]
71 #[doc(alias = "get_writable")]
72 pub fn get_mut(&mut self, idx: u32) -> Option<&mut BufferRef> {
73 unsafe {
74 let ptr = ffi::gst_buffer_list_get_writable(self.as_mut_ptr(), idx);
75 if ptr.is_null() {
76 None
77 } else {
78 Some(BufferRef::from_mut_ptr(ptr))
79 }
80 }
81 }
82
83 #[doc(alias = "gst_buffer_list_length")]
84 pub fn len(&self) -> usize {
85 unsafe { ffi::gst_buffer_list_length(self.as_mut_ptr()) as usize }
86 }
87
88 #[doc(alias = "gst_buffer_list_calculate_size")]
89 pub fn calculate_size(&self) -> usize {
90 unsafe { ffi::gst_buffer_list_calculate_size(self.as_mut_ptr()) }
91 }
92
93 pub fn is_empty(&self) -> bool {
94 self.len() == 0
95 }
96
97 pub fn iter(&self) -> Iter {
98 Iter::new(self)
99 }
100
101 pub fn iter_owned(&self) -> IterOwned {
102 IterOwned::new(self)
103 }
104
105 #[doc(alias = "gst_buffer_list_foreach")]
106 pub fn foreach<F: FnMut(&Buffer, u32) -> ControlFlow<(), ()>>(&self, func: F) -> bool {
107 unsafe extern "C" fn trampoline<F: FnMut(&Buffer, u32) -> ControlFlow<(), ()>>(
108 buffer: *mut *mut ffi::GstBuffer,
109 idx: u32,
110 user_data: glib::ffi::gpointer,
111 ) -> glib::ffi::gboolean {
112 let func = user_data as *const _ as usize as *mut F;
113 let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx);
114
115 matches!(res, ControlFlow::Continue(_)).into_glib()
116 }
117
118 unsafe {
119 let func_ptr: &F = &func;
120
121 from_glib(ffi::gst_buffer_list_foreach(
122 self.as_ptr() as *mut _,
123 Some(trampoline::<F>),
124 func_ptr as *const _ as usize as *mut _,
125 ))
126 }
127 }
128
129 #[doc(alias = "gst_buffer_list_foreach")]
130 pub fn foreach_mut<F: FnMut(Buffer, u32) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
131 &mut self,
132 func: F,
133 ) -> bool {
134 unsafe extern "C" fn trampoline<
135 F: FnMut(Buffer, u32) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
136 >(
137 buffer: *mut *mut ffi::GstBuffer,
138 idx: u32,
139 user_data: glib::ffi::gpointer,
140 ) -> glib::ffi::gboolean {
141 let func = user_data as *const _ as usize as *mut F;
142 let res = (*func)(
143 Buffer::from_glib_full(ptr::replace(
144 buffer as *mut *const ffi::GstBuffer,
145 ptr::null_mut::<ffi::GstBuffer>(),
146 )),
147 idx,
148 );
149
150 let (cont, res_buffer) = match res {
151 ControlFlow::Continue(res_buffer) => (true, res_buffer),
152 ControlFlow::Break(res_buffer) => (false, res_buffer),
153 };
154
155 match res_buffer {
156 None => {
157 *buffer = ptr::null_mut();
158 }
159 Some(new_buffer) => {
160 *buffer = new_buffer.into_glib_ptr();
161 }
162 }
163
164 cont.into_glib()
165 }
166
167 unsafe {
168 let func_ptr: &F = &func;
169
170 from_glib(ffi::gst_buffer_list_foreach(
171 self.as_ptr() as *mut _,
172 Some(trampoline::<F>),
173 func_ptr as *const _ as usize as *mut _,
174 ))
175 }
176 }
177}
178
179impl Default for BufferList {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185impl fmt::Debug for BufferList {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 BufferListRef::fmt(self, f)
188 }
189}
190
191impl fmt::Debug for BufferListRef {
192 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
193 use crate::{utils::Displayable, ClockTime};
194
195 let size: usize = self.iter().map(|b: &BufferRef| b.size()).sum::<usize>();
196 let (pts: Option, dts: Option) = self
197 .get(0)
198 .map(|b| (b.pts(), b.dts()))
199 .unwrap_or((ClockTime::NONE, ClockTime::NONE));
200
201 f&mut DebugStruct<'_, '_>.debug_struct("BufferList")
202 .field("ptr", &self.as_ptr())
203 .field("buffers", &self.len())
204 .field("pts", &pts.display())
205 .field("dts", &dts.display())
206 .field(name:"size", &size)
207 .finish()
208 }
209}
210
211macro_rules! define_iter(
212 ($name:ident, $styp:ty, $get_item:expr) => {
213 #[derive(Debug)]
214 pub struct $name<'a> {
215 list: &'a BufferListRef,
216 idx: usize,
217 size: usize,
218 }
219
220 impl<'a> $name<'a> {
221 fn new(list: &'a BufferListRef) -> $name<'a> {
222 skip_assert_initialized!();
223 $name {
224 list,
225 idx: 0,
226 size: list.len() as usize,
227 }
228 }
229 }
230
231 #[allow(clippy::redundant_closure_call)]
232 impl<'a> Iterator for $name<'a> {
233 type Item = $styp;
234
235 fn next(&mut self) -> Option<Self::Item> {
236 if self.idx >= self.size {
237 return None;
238 }
239
240 let item = $get_item(self.list, self.idx as u32).unwrap();
241 self.idx += 1;
242
243 Some(item)
244 }
245
246 fn size_hint(&self) -> (usize, Option<usize>) {
247 let remaining = self.size - self.idx;
248
249 (remaining, Some(remaining))
250 }
251
252 fn count(self) -> usize {
253 self.size - self.idx
254 }
255
256 fn nth(&mut self, n: usize) -> Option<Self::Item> {
257 let (end, overflow) = self.idx.overflowing_add(n);
258 if end >= self.size || overflow {
259 self.idx = self.size;
260 None
261 } else {
262 self.idx = end + 1;
263 Some($get_item(self.list, end as u32).unwrap())
264 }
265 }
266
267 fn last(self) -> Option<Self::Item> {
268 if self.idx == self.size {
269 None
270 } else {
271 Some($get_item(self.list, self.size as u32 - 1).unwrap())
272 }
273 }
274 }
275
276 #[allow(clippy::redundant_closure_call)]
277 impl<'a> DoubleEndedIterator for $name<'a> {
278 fn next_back(&mut self) -> Option<Self::Item> {
279 if self.idx == self.size {
280 return None;
281 }
282
283 self.size -= 1;
284 Some($get_item(self.list, self.size as u32).unwrap())
285 }
286
287 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
288 let (end, overflow) = self.size.overflowing_sub(n);
289 if end <= self.idx || overflow {
290 self.idx = self.size;
291 None
292 } else {
293 self.size = end - 1;
294 Some($get_item(self.list, self.size as u32).unwrap())
295 }
296 }
297 }
298
299 impl<'a> ExactSizeIterator for $name<'a> {}
300 impl<'a> std::iter::FusedIterator for $name<'a> {}
301 }
302);
303
304define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
305 list.get(idx)
306});
307
308define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
309 list.get_owned(idx)
310});
311
312impl<'a> IntoIterator for &'a BufferListRef {
313 type IntoIter = Iter<'a>;
314 type Item = &'a BufferRef;
315
316 fn into_iter(self) -> Self::IntoIter {
317 self.iter()
318 }
319}
320
321impl From<Buffer> for BufferList {
322 fn from(value: Buffer) -> Self {
323 skip_assert_initialized!();
324
325 let mut list: BufferList = BufferList::new_sized(size:1);
326 {
327 let list: &mut BufferListRef = list.get_mut().unwrap();
328 list.add(buffer:value);
329 }
330 list
331 }
332}
333
334impl<const N: usize> From<[Buffer; N]> for BufferList {
335 fn from(value: [Buffer; N]) -> Self {
336 skip_assert_initialized!();
337
338 let mut list: BufferList = BufferList::new_sized(N);
339 {
340 let list: &mut BufferListRef = list.get_mut().unwrap();
341 value.into_iter().for_each(|b: Buffer| list.add(buffer:b));
342 }
343 list
344 }
345}
346
347impl std::iter::FromIterator<Buffer> for BufferList {
348 fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
349 assert_initialized_main_thread!();
350
351 let iter: ::IntoIter = iter.into_iter();
352
353 let mut list: BufferList = BufferList::new_sized(size:iter.size_hint().0);
354
355 {
356 let list: &mut BufferListRef = list.get_mut().unwrap();
357 iter.for_each(|b: Buffer| list.add(buffer:b));
358 }
359
360 list
361 }
362}
363
364impl std::iter::Extend<Buffer> for BufferListRef {
365 fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
366 iter.into_iter().for_each(|b: Buffer| self.add(buffer:b));
367 }
368}
369
370#[cfg(test)]
371mod tests {
372 use super::*;
373 use crate::ClockTime;
374
375 #[test]
376 fn test_foreach() {
377 crate::init().unwrap();
378
379 let mut buffer_list = BufferList::new();
380 {
381 let buffer_list = buffer_list.get_mut().unwrap();
382 let mut buffer = Buffer::new();
383 buffer.get_mut().unwrap().set_pts(ClockTime::ZERO);
384 buffer_list.add(buffer);
385
386 let mut buffer = Buffer::new();
387 buffer.get_mut().unwrap().set_pts(ClockTime::SECOND);
388 buffer_list.add(buffer);
389 }
390
391 let mut res = vec![];
392 buffer_list.foreach(|buffer, idx| {
393 res.push((buffer.pts(), idx));
394 ControlFlow::Continue(())
395 });
396
397 assert_eq!(
398 res,
399 &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
400 );
401 }
402
403 #[test]
404 fn test_foreach_mut() {
405 crate::init().unwrap();
406
407 let mut buffer_list = BufferList::new();
408 {
409 let buffer_list = buffer_list.get_mut().unwrap();
410 let mut buffer = Buffer::new();
411 buffer.get_mut().unwrap().set_pts(ClockTime::ZERO);
412 buffer_list.add(buffer);
413
414 let mut buffer = Buffer::new();
415 buffer.get_mut().unwrap().set_pts(ClockTime::SECOND);
416 buffer_list.add(buffer);
417
418 let mut buffer = Buffer::new();
419 buffer.get_mut().unwrap().set_pts(2 * ClockTime::SECOND);
420 buffer_list.add(buffer);
421 }
422
423 let mut res = vec![];
424 buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
425 res.push((buffer.pts(), idx));
426
427 if let Some(ClockTime::ZERO) = buffer.pts() {
428 ControlFlow::Continue(Some(buffer))
429 } else if let Some(ClockTime::SECOND) = buffer.pts() {
430 ControlFlow::Continue(None)
431 } else {
432 let mut new_buffer = Buffer::new();
433 new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
434 ControlFlow::Continue(Some(new_buffer))
435 }
436 });
437
438 assert_eq!(
439 res,
440 &[
441 (Some(ClockTime::ZERO), 0),
442 (Some(ClockTime::SECOND), 1),
443 (Some(2 * ClockTime::SECOND), 1)
444 ]
445 );
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(3 * ClockTime::SECOND), 1)]
456 );
457 }
458}
459