gstreamer: buffer: Use ranges instead of offset/length parameter pairs

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/497

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1363>
This commit is contained in:
Sebastian Dröge 2023-12-10 20:35:43 +02:00
parent cd30854c2b
commit 96de51a7b7
6 changed files with 99 additions and 91 deletions

View file

@ -352,7 +352,7 @@ pub trait BaseSrcImplExt: sealed::Sealed + ObjectSubclass {
passed_buffer.set_size(copied_size); 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), Ok(_) => Ok(CreateSuccess::FilledBuffer),
Err(_) => { Err(_) => {
gst::error!( gst::error!(
@ -775,12 +775,7 @@ unsafe extern "C" fn base_src_create<T: BaseSrcImpl>(
passed_buffer.set_size(copied_size); passed_buffer.set_size(copied_size);
} }
match new_buffer.copy_into( match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) {
passed_buffer,
gst::BUFFER_COPY_METADATA,
0,
None,
) {
Ok(_) => gst::FlowReturn::Ok, Ok(_) => gst::FlowReturn::Ok,
Err(_) => { Err(_) => {
gst::error!( gst::error!(

View file

@ -154,7 +154,7 @@ pub trait PushSrcImplExt: sealed::Sealed + ObjectSubclass {
passed_buffer.set_size(copied_size); 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), Ok(_) => Ok(CreateSuccess::FilledBuffer),
Err(_) => { Err(_) => {
gst::error!( gst::error!(
@ -282,12 +282,7 @@ unsafe extern "C" fn push_src_create<T: PushSrcImpl>(
passed_buffer.set_size(copied_size); passed_buffer.set_size(copied_size);
} }
match new_buffer.copy_into( match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) {
passed_buffer,
gst::BUFFER_COPY_METADATA,
0,
None,
) {
Ok(_) => gst::FlowReturn::Ok, Ok(_) => gst::FlowReturn::Ok,
Err(_) => { Err(_) => {
gst::error!( gst::error!(

View file

@ -4,7 +4,7 @@ use std::{
cmp, fmt, cmp, fmt,
marker::PhantomData, marker::PhantomData,
mem, ops, mem, ops,
ops::{Bound, ControlFlow, RangeBounds}, ops::{Bound, ControlFlow, Range, RangeBounds},
ptr, slice, u64, usize, ptr, slice, u64, usize,
}; };
@ -299,20 +299,53 @@ impl BufferRef {
} }
} }
pub(crate) fn byte_range_into_offset_len(
&self,
range: impl RangeBounds<usize>,
) -> 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")] #[doc(alias = "gst_buffer_copy_region")]
pub fn copy_region( pub fn copy_region(
&self, &self,
flags: crate::BufferCopyFlags, flags: crate::BufferCopyFlags,
offset: usize, range: impl RangeBounds<usize>,
size: Option<usize>,
) -> Result<Buffer, glib::BoolError> { ) -> Result<Buffer, glib::BoolError> {
let size_real = size.unwrap_or(usize::MAX); let (offset, size) = self.byte_range_into_offset_len(range)?;
unsafe { unsafe {
Option::<_>::from_glib_full(ffi::gst_buffer_copy_region( Option::<_>::from_glib_full(ffi::gst_buffer_copy_region(
self.as_mut_ptr(), self.as_mut_ptr(),
flags.into_glib(), flags.into_glib(),
offset, offset,
size_real, size,
)) ))
.ok_or_else(|| glib::bool_error!("Failed to copy region of buffer")) .ok_or_else(|| glib::bool_error!("Failed to copy region of buffer"))
} }
@ -323,10 +356,10 @@ impl BufferRef {
&self, &self,
dest: &mut BufferRef, dest: &mut BufferRef,
flags: crate::BufferCopyFlags, flags: crate::BufferCopyFlags,
offset: usize, range: impl RangeBounds<usize>,
size: Option<usize>,
) -> Result<(), glib::BoolError> { ) -> Result<(), glib::BoolError> {
let size_real = size.unwrap_or(usize::MAX); let (offset, size) = self.byte_range_into_offset_len(range)?;
unsafe { unsafe {
glib::result_from_gboolean!( glib::result_from_gboolean!(
ffi::gst_buffer_copy_into( ffi::gst_buffer_copy_into(
@ -334,7 +367,7 @@ impl BufferRef {
self.as_mut_ptr(), self.as_mut_ptr(),
flags.into_glib(), flags.into_glib(),
offset, offset,
size_real, size,
), ),
"Failed to copy into destination buffer", "Failed to copy into destination buffer",
) )
@ -623,7 +656,9 @@ impl BufferRef {
} }
#[doc(alias = "gst_buffer_find_memory")] #[doc(alias = "gst_buffer_find_memory")]
pub fn find_memory(&self, offset: usize, size: Option<usize>) -> Option<(u32, u32, usize)> { pub fn find_memory(&self, range: impl RangeBounds<usize>) -> Option<(Range<u32>, usize)> {
let (offset, size) = self.byte_range_into_offset_len(range).ok()?;
unsafe { unsafe {
let mut idx = mem::MaybeUninit::uninit(); let mut idx = mem::MaybeUninit::uninit();
let mut length = mem::MaybeUninit::uninit(); let mut length = mem::MaybeUninit::uninit();
@ -632,14 +667,17 @@ impl BufferRef {
let res = from_glib(ffi::gst_buffer_find_memory( let res = from_glib(ffi::gst_buffer_find_memory(
self.as_mut_ptr(), self.as_mut_ptr(),
offset, offset,
size.unwrap_or(usize::MAX), size,
idx.as_mut_ptr(), idx.as_mut_ptr(),
length.as_mut_ptr(), length.as_mut_ptr(),
skip.as_mut_ptr(), skip.as_mut_ptr(),
)); ));
if res { 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 { } else {
None None
} }
@ -684,17 +722,11 @@ impl BufferRef {
#[doc(alias = "get_memory_range")] #[doc(alias = "get_memory_range")]
#[doc(alias = "gst_buffer_get_memory_range")] #[doc(alias = "gst_buffer_get_memory_range")]
pub fn memory_range(&self, idx: u32, length: Option<u32>) -> Option<Memory> { pub fn memory_range(&self, range: impl RangeBounds<u32>) -> Option<Memory> {
assert!(idx + length.unwrap_or(0) < self.n_memory()); let (idx, len) = self.memory_range_into_idx_len(range).ok()?;
unsafe { unsafe {
let res = ffi::gst_buffer_get_memory_range( let res = ffi::gst_buffer_get_memory_range(self.as_mut_ptr(), idx, len);
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
);
if res.is_null() { if res.is_null() {
None None
} else { } else {
@ -704,17 +736,9 @@ impl BufferRef {
} }
#[doc(alias = "gst_buffer_insert_memory")] #[doc(alias = "gst_buffer_insert_memory")]
pub fn insert_memory(&mut self, idx: Option<u32>, mem: Memory) { pub fn insert_memory(&mut self, idx: u32, mem: Memory) {
unsafe { assert!(idx <= self.n_memory());
ffi::gst_buffer_insert_memory( unsafe { ffi::gst_buffer_insert_memory(self.as_mut_ptr(), idx as i32, mem.into_glib_ptr()) }
self.as_mut_ptr(),
match idx {
Some(val) => val as i32,
None => -1,
},
mem.into_glib_ptr(),
)
}
} }
#[doc(alias = "gst_buffer_is_all_memory_writable")] #[doc(alias = "gst_buffer_is_all_memory_writable")]
@ -723,15 +747,16 @@ impl BufferRef {
} }
#[doc(alias = "gst_buffer_is_memory_range_writable")] #[doc(alias = "gst_buffer_is_memory_range_writable")]
pub fn is_memory_range_writable(&self, idx: u32, length: Option<u16>) -> bool { pub fn is_memory_range_writable(&self, range: impl RangeBounds<u32>) -> bool {
let Some((idx, len)) = self.memory_range_into_idx_len(range).ok() else {
return false;
};
unsafe { unsafe {
from_glib(ffi::gst_buffer_is_memory_range_writable( from_glib(ffi::gst_buffer_is_memory_range_writable(
self.as_mut_ptr(), self.as_mut_ptr(),
idx, idx,
match length { len,
Some(val) => val as i32,
None => -1,
},
)) ))
} }
} }
@ -780,18 +805,12 @@ impl BufferRef {
} }
#[doc(alias = "gst_buffer_remove_memory_range")] #[doc(alias = "gst_buffer_remove_memory_range")]
pub fn remove_memory_range(&mut self, idx: u32, length: Option<u32>) { pub fn remove_memory_range(&mut self, range: impl RangeBounds<u32>) {
assert!(idx + length.unwrap_or(0) < self.n_memory()); let (idx, len) = self
unsafe { .memory_range_into_idx_len(range)
ffi::gst_buffer_remove_memory_range( .expect("Invalid memory range");
self.as_mut_ptr(),
idx, unsafe { ffi::gst_buffer_remove_memory_range(self.as_mut_ptr(), idx, len) }
match length {
Some(val) => val as i32,
None => -1,
},
)
}
} }
#[doc(alias = "gst_buffer_replace_all_memory")] #[doc(alias = "gst_buffer_replace_all_memory")]
@ -806,18 +825,13 @@ impl BufferRef {
} }
#[doc(alias = "gst_buffer_replace_memory_range")] #[doc(alias = "gst_buffer_replace_memory_range")]
pub fn replace_memory_range(&mut self, idx: u32, length: Option<u32>, mem: Memory) { pub fn replace_memory_range(&mut self, range: impl RangeBounds<u32>, mem: Memory) {
assert!(idx + length.unwrap_or(0) < self.n_memory()); let (idx, len) = self
.memory_range_into_idx_len(range)
.expect("Invalid memory range");
unsafe { unsafe {
ffi::gst_buffer_replace_memory_range( ffi::gst_buffer_replace_memory_range(self.as_mut_ptr(), idx, len, mem.into_glib_ptr())
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
mem.into_glib_ptr(),
)
} }
} }
@ -1528,14 +1542,14 @@ impl<'a> Dump<'a> {
} }
// This can't really fail because of the above // This can't really fail because of the above
let (idx, _, skip) = self let (memory_range, skip) = self
.buffer .buffer
.find_memory(start_idx, None) .find_memory(start_idx..)
.expect("can't find memory"); .expect("can't find memory");
let chunks = BufferChunked16Iter { let chunks = BufferChunked16Iter {
buffer: self.buffer, buffer: self.buffer,
mem_idx: idx, mem_idx: memory_range.start,
mem_len: n_memory, mem_len: n_memory,
map: None, map: None,
map_offset: skip, map_offset: skip,

View file

@ -69,18 +69,18 @@ macro_rules! define_seek_impl(
// Work around lifetime annotation issues with closures // Work around lifetime annotation issues with closures
let buffer_ref: fn(&Self) -> &BufferRef = $get_buffer_ref; let buffer_ref: fn(&Self) -> &BufferRef = $get_buffer_ref;
let (idx, _, skip) = buffer_ref(self) let (range, skip) = buffer_ref(self)
.find_memory(self.cur_offset as usize, None) .find_memory(self.cur_offset as usize..)
.expect("Failed to find memory"); .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 { unsafe {
ffi::gst_memory_unmap(self.map_info.memory, &mut self.map_info); ffi::gst_memory_unmap(self.map_info.memory, &mut self.map_info);
self.map_info.memory = ptr::null_mut(); self.map_info.memory = ptr::null_mut();
} }
} }
self.cur_mem_idx = idx; self.cur_mem_idx = range.start;
self.cur_mem_offset = skip; self.cur_mem_offset = skip;
Ok(self.cur_offset) Ok(self.cur_offset)

View file

@ -3,7 +3,11 @@
#[cfg(feature = "v1_20")] #[cfg(feature = "v1_20")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))] #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
use std::ptr; use std::ptr;
use std::{fmt, marker::PhantomData, ops}; use std::{
fmt,
marker::PhantomData,
ops::{self, RangeBounds},
};
use glib::translate::*; use glib::translate::*;
@ -228,8 +232,7 @@ impl<'a, T> MetaRef<'a, T> {
&self, &self,
buffer: &mut BufferRef, buffer: &mut BufferRef,
region: bool, region: bool,
offset: usize, range: impl RangeBounds<usize>,
size: Option<usize>,
) -> Result<(), glib::BoolError> ) -> Result<(), glib::BoolError>
where where
T: MetaAPI, T: MetaAPI,
@ -238,6 +241,8 @@ impl<'a, T> MetaRef<'a, T> {
static TRANSFORM_COPY: Lazy<glib::Quark> = Lazy::new(|| glib::Quark::from_str("gst-copy")); static TRANSFORM_COPY: Lazy<glib::Quark> = Lazy::new(|| glib::Quark::from_str("gst-copy"));
let (offset, size) = self.buffer.byte_range_into_offset_len(range)?;
unsafe { unsafe {
let info = *(*self.upcast_ref().as_ptr()).info; let info = *(*self.upcast_ref().as_ptr()).info;
let Some(transform_func) = info.transform_func else { let Some(transform_func) = info.transform_func else {
@ -249,7 +254,7 @@ impl<'a, T> MetaRef<'a, T> {
let mut copy_data = ffi::GstMetaTransformCopy { let mut copy_data = ffi::GstMetaTransformCopy {
region: region.into_glib(), region: region.into_glib(),
offset, offset,
size: size.unwrap_or(usize::MAX), size,
}; };
glib::result_from_gboolean!( glib::result_from_gboolean!(
@ -361,13 +366,12 @@ impl<'a, T, U> MetaRefMut<'a, T, U> {
&self, &self,
buffer: &mut BufferRef, buffer: &mut BufferRef,
region: bool, region: bool,
offset: usize, range: impl RangeBounds<usize>,
size: Option<usize>,
) -> Result<(), glib::BoolError> ) -> Result<(), glib::BoolError>
where where
T: MetaAPI, T: MetaAPI,
{ {
self.as_meta_ref().copy(buffer, region, offset, size) self.as_meta_ref().copy(buffer, region, range)
} }
#[inline] #[inline]
@ -947,7 +951,7 @@ mod tests {
{ {
let meta = buffer.meta::<ReferenceTimestampMeta>().unwrap(); let meta = buffer.meta::<ReferenceTimestampMeta>().unwrap();
let buffer_dest = buffer_dest.get_mut().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::<ReferenceTimestampMeta>().unwrap(); let meta = buffer_dest.meta::<ReferenceTimestampMeta>().unwrap();

View file

@ -1299,7 +1299,7 @@ where
passed_buffer.set_size(copied_size); 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(), Ok(_) => FlowReturn::Ok.into_glib(),
Err(_) => { Err(_) => {
crate::error!( crate::error!(