diff --git a/gstreamer-base/src/subclass/base_src.rs b/gstreamer-base/src/subclass/base_src.rs index 1f0e74622..327eb0fbb 100644 --- a/gstreamer-base/src/subclass/base_src.rs +++ b/gstreamer-base/src/subclass/base_src.rs @@ -352,7 +352,7 @@ pub trait BaseSrcImplExt: sealed::Sealed + ObjectSubclass { passed_buffer.set_size(copied_size); } - match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, 0, None) { + match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) { Ok(_) => Ok(CreateSuccess::FilledBuffer), Err(_) => { gst::error!( @@ -775,12 +775,7 @@ unsafe extern "C" fn base_src_create( passed_buffer.set_size(copied_size); } - match new_buffer.copy_into( - passed_buffer, - gst::BUFFER_COPY_METADATA, - 0, - None, - ) { + match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) { Ok(_) => gst::FlowReturn::Ok, Err(_) => { gst::error!( diff --git a/gstreamer-base/src/subclass/push_src.rs b/gstreamer-base/src/subclass/push_src.rs index 5616cba45..6782b0e05 100644 --- a/gstreamer-base/src/subclass/push_src.rs +++ b/gstreamer-base/src/subclass/push_src.rs @@ -154,7 +154,7 @@ pub trait PushSrcImplExt: sealed::Sealed + ObjectSubclass { passed_buffer.set_size(copied_size); } - match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, 0, None) { + match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) { Ok(_) => Ok(CreateSuccess::FilledBuffer), Err(_) => { gst::error!( @@ -282,12 +282,7 @@ unsafe extern "C" fn push_src_create( passed_buffer.set_size(copied_size); } - match new_buffer.copy_into( - passed_buffer, - gst::BUFFER_COPY_METADATA, - 0, - None, - ) { + match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) { Ok(_) => gst::FlowReturn::Ok, Err(_) => { gst::error!( diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index efc4e0433..5d8dab5be 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -4,7 +4,7 @@ use std::{ cmp, fmt, marker::PhantomData, mem, ops, - ops::{Bound, ControlFlow, RangeBounds}, + ops::{Bound, ControlFlow, Range, RangeBounds}, ptr, slice, u64, usize, }; @@ -299,20 +299,53 @@ impl BufferRef { } } + pub(crate) fn byte_range_into_offset_len( + &self, + range: impl RangeBounds, + ) -> Result<(usize, usize), glib::BoolError> { + let size = self.size(); + + let start_idx = match range.start_bound() { + ops::Bound::Included(idx) if *idx >= size => { + return Err(glib::bool_error!("Invalid range start")); + } + ops::Bound::Included(idx) => *idx, + ops::Bound::Excluded(idx) if idx.checked_add(1).map_or(true, |idx| idx >= size) => { + return Err(glib::bool_error!("Invalid range start")); + } + ops::Bound::Excluded(idx) => *idx + 1, + ops::Bound::Unbounded => 0, + }; + + let end_idx = match range.end_bound() { + ops::Bound::Included(idx) if idx.checked_add(1).map_or(true, |idx| idx >= size) => { + return Err(glib::bool_error!("Invalid range end")); + } + ops::Bound::Included(idx) => *idx + 1, + ops::Bound::Excluded(idx) if *idx >= size => { + return Err(glib::bool_error!("Invalid range end")); + } + ops::Bound::Excluded(idx) => *idx, + ops::Bound::Unbounded => size, + }; + + Ok((start_idx, end_idx - start_idx)) + } + #[doc(alias = "gst_buffer_copy_region")] pub fn copy_region( &self, flags: crate::BufferCopyFlags, - offset: usize, - size: Option, + range: impl RangeBounds, ) -> Result { - let size_real = size.unwrap_or(usize::MAX); + let (offset, size) = self.byte_range_into_offset_len(range)?; + unsafe { Option::<_>::from_glib_full(ffi::gst_buffer_copy_region( self.as_mut_ptr(), flags.into_glib(), offset, - size_real, + size, )) .ok_or_else(|| glib::bool_error!("Failed to copy region of buffer")) } @@ -323,10 +356,10 @@ impl BufferRef { &self, dest: &mut BufferRef, flags: crate::BufferCopyFlags, - offset: usize, - size: Option, + range: impl RangeBounds, ) -> Result<(), glib::BoolError> { - let size_real = size.unwrap_or(usize::MAX); + let (offset, size) = self.byte_range_into_offset_len(range)?; + unsafe { glib::result_from_gboolean!( ffi::gst_buffer_copy_into( @@ -334,7 +367,7 @@ impl BufferRef { self.as_mut_ptr(), flags.into_glib(), offset, - size_real, + size, ), "Failed to copy into destination buffer", ) @@ -623,7 +656,9 @@ impl BufferRef { } #[doc(alias = "gst_buffer_find_memory")] - pub fn find_memory(&self, offset: usize, size: Option) -> Option<(u32, u32, usize)> { + pub fn find_memory(&self, range: impl RangeBounds) -> Option<(Range, usize)> { + let (offset, size) = self.byte_range_into_offset_len(range).ok()?; + unsafe { let mut idx = mem::MaybeUninit::uninit(); let mut length = mem::MaybeUninit::uninit(); @@ -632,14 +667,17 @@ impl BufferRef { let res = from_glib(ffi::gst_buffer_find_memory( self.as_mut_ptr(), offset, - size.unwrap_or(usize::MAX), + size, idx.as_mut_ptr(), length.as_mut_ptr(), skip.as_mut_ptr(), )); if res { - Some((idx.assume_init(), length.assume_init(), skip.assume_init())) + let idx = idx.assume_init(); + let length = length.assume_init(); + let skip = skip.assume_init(); + Some((idx..(idx + length), skip)) } else { None } @@ -684,17 +722,11 @@ impl BufferRef { #[doc(alias = "get_memory_range")] #[doc(alias = "gst_buffer_get_memory_range")] - pub fn memory_range(&self, idx: u32, length: Option) -> Option { - assert!(idx + length.unwrap_or(0) < self.n_memory()); + pub fn memory_range(&self, range: impl RangeBounds) -> Option { + let (idx, len) = self.memory_range_into_idx_len(range).ok()?; + unsafe { - let res = ffi::gst_buffer_get_memory_range( - self.as_mut_ptr(), - idx, - match length { - Some(val) => val as i32, - None => -1, - }, - ); + let res = ffi::gst_buffer_get_memory_range(self.as_mut_ptr(), idx, len); if res.is_null() { None } else { @@ -704,17 +736,9 @@ impl BufferRef { } #[doc(alias = "gst_buffer_insert_memory")] - pub fn insert_memory(&mut self, idx: Option, mem: Memory) { - unsafe { - ffi::gst_buffer_insert_memory( - self.as_mut_ptr(), - match idx { - Some(val) => val as i32, - None => -1, - }, - mem.into_glib_ptr(), - ) - } + pub fn insert_memory(&mut self, idx: u32, mem: Memory) { + assert!(idx <= self.n_memory()); + unsafe { ffi::gst_buffer_insert_memory(self.as_mut_ptr(), idx as i32, mem.into_glib_ptr()) } } #[doc(alias = "gst_buffer_is_all_memory_writable")] @@ -723,15 +747,16 @@ impl BufferRef { } #[doc(alias = "gst_buffer_is_memory_range_writable")] - pub fn is_memory_range_writable(&self, idx: u32, length: Option) -> bool { + pub fn is_memory_range_writable(&self, range: impl RangeBounds) -> bool { + let Some((idx, len)) = self.memory_range_into_idx_len(range).ok() else { + return false; + }; + unsafe { from_glib(ffi::gst_buffer_is_memory_range_writable( self.as_mut_ptr(), idx, - match length { - Some(val) => val as i32, - None => -1, - }, + len, )) } } @@ -780,18 +805,12 @@ impl BufferRef { } #[doc(alias = "gst_buffer_remove_memory_range")] - pub fn remove_memory_range(&mut self, idx: u32, length: Option) { - assert!(idx + length.unwrap_or(0) < self.n_memory()); - unsafe { - ffi::gst_buffer_remove_memory_range( - self.as_mut_ptr(), - idx, - match length { - Some(val) => val as i32, - None => -1, - }, - ) - } + pub fn remove_memory_range(&mut self, range: impl RangeBounds) { + let (idx, len) = self + .memory_range_into_idx_len(range) + .expect("Invalid memory range"); + + unsafe { ffi::gst_buffer_remove_memory_range(self.as_mut_ptr(), idx, len) } } #[doc(alias = "gst_buffer_replace_all_memory")] @@ -806,18 +825,13 @@ impl BufferRef { } #[doc(alias = "gst_buffer_replace_memory_range")] - pub fn replace_memory_range(&mut self, idx: u32, length: Option, mem: Memory) { - assert!(idx + length.unwrap_or(0) < self.n_memory()); + pub fn replace_memory_range(&mut self, range: impl RangeBounds, mem: Memory) { + let (idx, len) = self + .memory_range_into_idx_len(range) + .expect("Invalid memory range"); + unsafe { - ffi::gst_buffer_replace_memory_range( - self.as_mut_ptr(), - idx, - match length { - Some(val) => val as i32, - None => -1, - }, - mem.into_glib_ptr(), - ) + ffi::gst_buffer_replace_memory_range(self.as_mut_ptr(), idx, len, mem.into_glib_ptr()) } } @@ -1528,14 +1542,14 @@ impl<'a> Dump<'a> { } // This can't really fail because of the above - let (idx, _, skip) = self + let (memory_range, skip) = self .buffer - .find_memory(start_idx, None) + .find_memory(start_idx..) .expect("can't find memory"); let chunks = BufferChunked16Iter { buffer: self.buffer, - mem_idx: idx, + mem_idx: memory_range.start, mem_len: n_memory, map: None, map_offset: skip, diff --git a/gstreamer/src/buffer_cursor.rs b/gstreamer/src/buffer_cursor.rs index 7fc28839a..7ff7cdab1 100644 --- a/gstreamer/src/buffer_cursor.rs +++ b/gstreamer/src/buffer_cursor.rs @@ -69,18 +69,18 @@ macro_rules! define_seek_impl( // Work around lifetime annotation issues with closures let buffer_ref: fn(&Self) -> &BufferRef = $get_buffer_ref; - let (idx, _, skip) = buffer_ref(self) - .find_memory(self.cur_offset as usize, None) + let (range, skip) = buffer_ref(self) + .find_memory(self.cur_offset as usize..) .expect("Failed to find memory"); - if idx != self.cur_mem_idx && !self.map_info.memory.is_null() { + if range.start != self.cur_mem_idx && !self.map_info.memory.is_null() { unsafe { ffi::gst_memory_unmap(self.map_info.memory, &mut self.map_info); self.map_info.memory = ptr::null_mut(); } } - self.cur_mem_idx = idx; + self.cur_mem_idx = range.start; self.cur_mem_offset = skip; Ok(self.cur_offset) diff --git a/gstreamer/src/meta.rs b/gstreamer/src/meta.rs index 0aaf24b92..79b4c3141 100644 --- a/gstreamer/src/meta.rs +++ b/gstreamer/src/meta.rs @@ -3,7 +3,11 @@ #[cfg(feature = "v1_20")] #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))] use std::ptr; -use std::{fmt, marker::PhantomData, ops}; +use std::{ + fmt, + marker::PhantomData, + ops::{self, RangeBounds}, +}; use glib::translate::*; @@ -228,8 +232,7 @@ impl<'a, T> MetaRef<'a, T> { &self, buffer: &mut BufferRef, region: bool, - offset: usize, - size: Option, + range: impl RangeBounds, ) -> Result<(), glib::BoolError> where T: MetaAPI, @@ -238,6 +241,8 @@ impl<'a, T> MetaRef<'a, T> { static TRANSFORM_COPY: Lazy = Lazy::new(|| glib::Quark::from_str("gst-copy")); + let (offset, size) = self.buffer.byte_range_into_offset_len(range)?; + unsafe { let info = *(*self.upcast_ref().as_ptr()).info; let Some(transform_func) = info.transform_func else { @@ -249,7 +254,7 @@ impl<'a, T> MetaRef<'a, T> { let mut copy_data = ffi::GstMetaTransformCopy { region: region.into_glib(), offset, - size: size.unwrap_or(usize::MAX), + size, }; glib::result_from_gboolean!( @@ -361,13 +366,12 @@ impl<'a, T, U> MetaRefMut<'a, T, U> { &self, buffer: &mut BufferRef, region: bool, - offset: usize, - size: Option, + range: impl RangeBounds, ) -> Result<(), glib::BoolError> where T: MetaAPI, { - self.as_meta_ref().copy(buffer, region, offset, size) + self.as_meta_ref().copy(buffer, region, range) } #[inline] @@ -947,7 +951,7 @@ mod tests { { let meta = buffer.meta::().unwrap(); let buffer_dest = buffer_dest.get_mut().unwrap(); - meta.copy(buffer_dest, false, 0, None).unwrap(); + meta.copy(buffer_dest, false, ..).unwrap(); } let meta = buffer_dest.meta::().unwrap(); diff --git a/gstreamer/src/pad.rs b/gstreamer/src/pad.rs index c9a28ddb6..36ebb4234 100644 --- a/gstreamer/src/pad.rs +++ b/gstreamer/src/pad.rs @@ -1299,7 +1299,7 @@ where passed_buffer.set_size(copied_size); } - match new_buffer.copy_into(passed_buffer, crate::BUFFER_COPY_METADATA, 0, None) { + match new_buffer.copy_into(passed_buffer, crate::BUFFER_COPY_METADATA, ..) { Ok(_) => FlowReturn::Ok.into_glib(), Err(_) => { crate::error!(