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);
}
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<T: BaseSrcImpl>(
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!(

View file

@ -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<T: PushSrcImpl>(
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!(

View file

@ -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<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")]
pub fn copy_region(
&self,
flags: crate::BufferCopyFlags,
offset: usize,
size: Option<usize>,
range: impl RangeBounds<usize>,
) -> Result<Buffer, glib::BoolError> {
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<usize>,
range: impl RangeBounds<usize>,
) -> 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<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 {
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<u32>) -> Option<Memory> {
assert!(idx + length.unwrap_or(0) < self.n_memory());
pub fn memory_range(&self, range: impl RangeBounds<u32>) -> Option<Memory> {
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<u32>, 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<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 {
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<u32>) {
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<u32>) {
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<u32>, mem: Memory) {
assert!(idx + length.unwrap_or(0) < self.n_memory());
pub fn replace_memory_range(&mut self, range: impl RangeBounds<u32>, 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,

View file

@ -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)

View file

@ -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<usize>,
range: impl RangeBounds<usize>,
) -> Result<(), glib::BoolError>
where
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"));
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<usize>,
range: impl RangeBounds<usize>,
) -> 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::<ReferenceTimestampMeta>().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();

View file

@ -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!(