forked from mirrors/gstreamer-rs
gstreamer: memory: Use ranges instead of offset/size 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:
parent
96de51a7b7
commit
5c88bd0b5f
1 changed files with 90 additions and 54 deletions
|
@ -175,29 +175,72 @@ impl MemoryRef {
|
||||||
unsafe { from_glib(self.0.mini_object.flags) }
|
unsafe { from_glib(self.0.mini_object.flags) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_memory_copy")]
|
fn calculate_offset_size(&self, range: impl RangeBounds<usize>) -> (isize, isize) {
|
||||||
pub fn copy_range(&self, offset: isize, size: Option<usize>) -> Memory {
|
let size = self.size();
|
||||||
let new_offset = if offset < 0 {
|
|
||||||
assert!((-offset) as usize >= self.offset());
|
let start_offset = match range.start_bound() {
|
||||||
self.offset() - (-offset as usize)
|
Bound::Included(v) => *v,
|
||||||
} else {
|
Bound::Excluded(v) => v.checked_add(1).expect("Invalid start offset"),
|
||||||
self.offset()
|
Bound::Unbounded => 0,
|
||||||
.checked_add(offset as usize)
|
|
||||||
.expect("Too large offset")
|
|
||||||
};
|
};
|
||||||
|
assert!(start_offset < size, "Start offset after valid range");
|
||||||
|
|
||||||
assert!(new_offset + size.unwrap_or(0) < self.maxsize());
|
let end_offset = match range.end_bound() {
|
||||||
|
Bound::Included(v) => v.checked_add(1).expect("Invalid end offset"),
|
||||||
|
Bound::Excluded(v) => *v,
|
||||||
|
Bound::Unbounded => size,
|
||||||
|
};
|
||||||
|
assert!(end_offset <= size, "End offset after valid range");
|
||||||
|
|
||||||
unsafe {
|
// Cast from usize to isize because that's literally how this works in the
|
||||||
from_glib_full(ffi::gst_memory_copy(
|
// implementation and how the upper half of the usize range can be made use of.
|
||||||
self.as_mut_ptr(),
|
//
|
||||||
offset,
|
// The implementation works exploiting wraparounds.
|
||||||
match size {
|
let new_offset = start_offset as isize;
|
||||||
Some(val) => val as isize,
|
let new_size = end_offset.saturating_sub(start_offset) as isize;
|
||||||
None => -1,
|
|
||||||
},
|
(new_offset, new_size)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_offset_size_maxsize(&self, range: impl RangeBounds<usize>) -> (isize, isize) {
|
||||||
|
let maxsize = self.maxsize();
|
||||||
|
|
||||||
|
let start_offset = match range.start_bound() {
|
||||||
|
Bound::Included(v) => *v,
|
||||||
|
Bound::Excluded(v) => v.checked_add(1).expect("Invalid start offset"),
|
||||||
|
Bound::Unbounded => 0,
|
||||||
|
};
|
||||||
|
assert!(start_offset < maxsize, "Start offset after valid range");
|
||||||
|
|
||||||
|
let end_offset = match range.end_bound() {
|
||||||
|
Bound::Included(v) => v.checked_add(1).expect("Invalid end offset"),
|
||||||
|
Bound::Excluded(v) => *v,
|
||||||
|
Bound::Unbounded => maxsize,
|
||||||
|
};
|
||||||
|
assert!(end_offset <= maxsize, "End offset after valid range");
|
||||||
|
|
||||||
|
// Cast from usize to isize because that's literally how this works in the
|
||||||
|
// implementation and how the upper half of the usize range can be made use of.
|
||||||
|
//
|
||||||
|
// The implementation works by exploiting wraparounds.
|
||||||
|
let offset = self.offset();
|
||||||
|
|
||||||
|
let new_offset = start_offset.wrapping_sub(offset) as isize;
|
||||||
|
let new_size = end_offset.saturating_sub(start_offset) as isize;
|
||||||
|
|
||||||
|
(new_offset, new_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_memory_copy")]
|
||||||
|
pub fn copy_range(&self, range: impl RangeBounds<usize>) -> Memory {
|
||||||
|
let (offset, size) = self.calculate_offset_size(range);
|
||||||
|
unsafe { from_glib_full(ffi::gst_memory_copy(self.as_mut_ptr(), offset, size)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_memory_copy")]
|
||||||
|
pub fn copy_range_maxsize(&self, range: impl RangeBounds<usize>) -> Memory {
|
||||||
|
let (offset, size) = self.calculate_offset_size_maxsize(range);
|
||||||
|
unsafe { from_glib_full(ffi::gst_memory_copy(self.as_mut_ptr(), offset, size)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_memory_is_span")]
|
#[doc(alias = "gst_memory_is_span")]
|
||||||
|
@ -267,44 +310,27 @@ impl MemoryRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_memory_share")]
|
#[doc(alias = "gst_memory_share")]
|
||||||
pub fn share(&self, offset: isize, size: Option<usize>) -> Memory {
|
pub fn share(&self, range: impl RangeBounds<usize>) -> Memory {
|
||||||
let new_offset = if offset < 0 {
|
let (offset, size) = self.calculate_offset_size(range);
|
||||||
assert!((-offset) as usize >= self.offset());
|
unsafe { from_glib_full(ffi::gst_memory_share(self.as_ptr() as *mut _, offset, size)) }
|
||||||
self.offset() - (-offset as usize)
|
|
||||||
} else {
|
|
||||||
self.offset()
|
|
||||||
.checked_add(offset as usize)
|
|
||||||
.expect("Too large offset")
|
|
||||||
};
|
|
||||||
|
|
||||||
assert!(new_offset + size.unwrap_or(0) < self.maxsize());
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
from_glib_full(ffi::gst_memory_share(
|
|
||||||
self.as_ptr() as *mut _,
|
|
||||||
offset,
|
|
||||||
match size {
|
|
||||||
Some(val) => val as isize,
|
|
||||||
None => -1,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_memory_share")]
|
||||||
|
pub fn share_maxsize(&self, range: impl RangeBounds<usize>) -> Memory {
|
||||||
|
let (offset, size) = self.calculate_offset_size_maxsize(range);
|
||||||
|
unsafe { from_glib_full(ffi::gst_memory_share(self.as_ptr() as *mut _, offset, size)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_memory_resize")]
|
#[doc(alias = "gst_memory_resize")]
|
||||||
pub fn resize(&mut self, offset: isize, size: usize) {
|
pub fn resize(&mut self, range: impl RangeBounds<usize>) {
|
||||||
let new_offset = if offset < 0 {
|
let (offset, size) = self.calculate_offset_size(range);
|
||||||
assert!((-offset) as usize >= self.offset());
|
unsafe { ffi::gst_memory_resize(self.as_mut_ptr(), offset, size as usize) }
|
||||||
self.offset() - (-offset as usize)
|
}
|
||||||
} else {
|
|
||||||
self.offset()
|
|
||||||
.checked_add(offset as usize)
|
|
||||||
.expect("Too large offset")
|
|
||||||
};
|
|
||||||
|
|
||||||
assert!(new_offset + size < self.maxsize());
|
#[doc(alias = "gst_memory_resize")]
|
||||||
|
pub fn resize_maxsize(&mut self, range: impl RangeBounds<usize>) {
|
||||||
unsafe { ffi::gst_memory_resize(self.as_mut_ptr(), offset, size) }
|
let (offset, size) = self.calculate_offset_size_maxsize(range);
|
||||||
|
unsafe { ffi::gst_memory_resize(self.as_mut_ptr(), offset, size as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "gst_util_dump_mem")]
|
#[doc(alias = "gst_util_dump_mem")]
|
||||||
|
@ -947,7 +973,9 @@ mod tests {
|
||||||
crate::init().unwrap();
|
crate::init().unwrap();
|
||||||
|
|
||||||
let mem = crate::Memory::from_slice(vec![1, 2, 3, 4]);
|
let mem = crate::Memory::from_slice(vec![1, 2, 3, 4]);
|
||||||
let sub = mem.share(1, Some(2));
|
let sub = mem.share(1..=2); // [2, 3]
|
||||||
|
let sub_sub1 = sub.share(1..=1); // [3]
|
||||||
|
let sub_sub2 = sub.share_maxsize(0..4); // [1, 2, 3, 4]
|
||||||
|
|
||||||
let map = mem.map_readable().unwrap();
|
let map = mem.map_readable().unwrap();
|
||||||
assert_eq!(map.as_slice(), &[1, 2, 3, 4]);
|
assert_eq!(map.as_slice(), &[1, 2, 3, 4]);
|
||||||
|
@ -956,6 +984,14 @@ mod tests {
|
||||||
let map = sub.map_readable().unwrap();
|
let map = sub.map_readable().unwrap();
|
||||||
assert_eq!(map.as_slice(), &[2, 3]);
|
assert_eq!(map.as_slice(), &[2, 3]);
|
||||||
drop(map);
|
drop(map);
|
||||||
|
|
||||||
|
let map = sub_sub1.map_readable().unwrap();
|
||||||
|
assert_eq!(map.as_slice(), &[3]);
|
||||||
|
drop(map);
|
||||||
|
|
||||||
|
let map = sub_sub2.map_readable().unwrap();
|
||||||
|
assert_eq!(map.as_slice(), &[1, 2, 3, 4]);
|
||||||
|
drop(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue