From 9e0c980a49005678b6f8c6f98dd63d31e71518c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Apr 2020 19:28:28 +0300 Subject: [PATCH] gstreamer/buffer: Add iterators for iterating over the memories inside a buffer With immutable, mutable and owned variant. --- gstreamer/src/buffer.rs | 135 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 3 deletions(-) diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index fa3c4f597..65bf7fd01 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -605,9 +605,25 @@ impl BufferRef { ) } } + + pub fn iter_memories(&self) -> Iter { + Iter::new(self) + } + + pub fn iter_memories_mut(&mut self) -> Result { + if !self.is_all_memory_writable() { + Err(glib_bool_error!("Not all memory are writable")) + } else { + Ok(IterMut::new(self)) + } + } + + pub fn iter_memories_owned(&self) -> IterOwned { + IterOwned::new(self) + } } -macro_rules! define_iter( +macro_rules! define_meta_iter( ($name:ident, $typ:ty, $mtyp:ty, $prepare_buffer:expr, $from_ptr:expr) => { pub struct $name<'a, T: MetaAPI + 'a> { buffer: $typ, @@ -668,14 +684,14 @@ macro_rules! define_iter( } ); -define_iter!( +define_meta_iter!( MetaIter, &'a BufferRef, MetaRef<'a, T>, |buffer: *const gst_sys::GstBuffer| BufferRef::from_ptr(buffer), |buffer, meta| T::from_ptr(buffer, meta as *const ::GstType) ); -define_iter!( +define_meta_iter!( MetaIterMut, &'a mut BufferRef, MetaRefMut<'a, T, ::meta::Iterated>, @@ -683,6 +699,119 @@ define_iter!( |buffer: &'a mut BufferRef, meta| T::from_mut_ptr(buffer, meta as *mut ::GstType) ); +macro_rules! define_iter( + ($name:ident, $typ:ty, $mtyp:ty, $get_item:expr) => { + pub struct $name<'a> { + buffer: $typ, + idx: u32, + n_memory: u32, + } + + impl<'a> fmt::Debug for $name<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct(stringify!($name)) + .field("buffer", &self.buffer) + .field("idx", &self.idx) + .field("n_memory", &self.n_memory) + .finish() + } + } + + impl<'a> $name<'a> { + fn new(buffer: $typ) -> $name<'a> { + skip_assert_initialized!(); + + let n_memory = buffer.n_memory(); + + $name { + buffer, + idx: 0, + n_memory, + } + } + } + + impl<'a> Iterator for $name<'a> { + type Item = $mtyp; + + fn next(&mut self) -> Option { + if self.idx >= self.n_memory { + return None; + } + + #[allow(unused_unsafe)] + unsafe { + let item = $get_item(self.buffer, self.idx)?; + self.idx += 1; + Some(item) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.idx == self.n_memory { + return (0, Some(0)); + } + + let remaining = (self.n_memory - self.idx) as usize; + + (remaining, Some(remaining)) + } + } + + impl<'a> DoubleEndedIterator for $name<'a> { + fn next_back(&mut self) -> Option { + if self.idx == self.n_memory { + return None; + } + + self.n_memory -= 1; + + #[allow(unused_unsafe)] + unsafe { + $get_item(self.buffer, self.n_memory) + } + } + } + + impl<'a> ExactSizeIterator for $name<'a> {} + } +); + +define_iter!( + Iter, + &'a BufferRef, + &'a MemoryRef, + |buffer: &BufferRef, idx| { + let ptr = gst_sys::gst_buffer_peek_memory(buffer.as_mut_ptr(), idx); + if ptr.is_null() { + None + } else { + Some(MemoryRef::from_ptr(ptr as *const gst_sys::GstMemory)) + } + } +); + +define_iter!( + IterMut, + &'a mut BufferRef, + &'a mut MemoryRef, + |buffer: &mut BufferRef, idx| { + let ptr = gst_sys::gst_buffer_peek_memory(buffer.as_mut_ptr(), idx); + if ptr.is_null() { + None + } else { + Some(MemoryRef::from_mut_ptr(ptr as *mut gst_sys::GstMemory)) + } + } +); + +define_iter!( + IterOwned, + &'a BufferRef, + Memory, + |buffer: &BufferRef, idx| { buffer.get_memory(idx) } +); + impl fmt::Debug for BufferRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::cell::RefCell;