gstreamer-rs/gstreamer/src/bufferlist.rs

402 lines
11 KiB
Rust
Raw Normal View History

2020-12-15 10:53:31 +00:00
// Take a look at the license at the top of the repository in the LICENSE file.
2017-07-28 17:20:11 +00:00
use glib::translate::{from_glib, from_glib_full, from_glib_none, IntoGlib};
use std::fmt;
use std::ops::ControlFlow;
use std::ptr;
2017-07-28 17:20:11 +00:00
use crate::Buffer;
use crate::BufferRef;
2017-07-28 17:20:11 +00:00
mini_object_wrapper!(BufferList, BufferListRef, ffi::GstBufferList, || {
ffi::gst_buffer_list_get_type()
});
2017-07-28 17:20:11 +00:00
impl BufferList {
#[doc(alias = "gst_buffer_list_new")]
2017-07-28 17:20:11 +00:00
pub fn new() -> Self {
assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_buffer_list_new()) }
2017-07-28 17:20:11 +00:00
}
#[doc(alias = "gst_buffer_list_new_sized")]
2017-07-28 17:20:11 +00:00
pub fn new_sized(size: usize) -> Self {
assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_buffer_list_new_sized(size as u32)) }
2017-07-28 17:20:11 +00:00
}
}
impl BufferListRef {
#[doc(alias = "gst_buffer_list_insert")]
2017-07-28 17:20:11 +00:00
pub fn insert(&mut self, idx: i32, buffer: Buffer) {
unsafe {
ffi::gst_buffer_list_insert(self.as_mut_ptr(), idx, buffer.into_ptr());
2017-07-28 17:20:11 +00:00
}
}
#[doc(alias = "gst_buffer_list_add")]
2017-07-28 17:20:11 +00:00
pub fn add(&mut self, buffer: Buffer) {
self.insert(-1, buffer);
}
#[doc(alias = "gst_buffer_list_copy_deep")]
2017-07-28 17:20:11 +00:00
pub fn copy_deep(&self) -> BufferList {
unsafe { from_glib_full(ffi::gst_buffer_list_copy_deep(self.as_ptr())) }
2017-07-28 17:20:11 +00:00
}
#[doc(alias = "gst_buffer_list_remove")]
2017-07-28 17:20:11 +00:00
pub fn remove(&mut self, idx: u32, len: u32) {
unsafe { ffi::gst_buffer_list_remove(self.as_mut_ptr(), idx, len) }
2017-07-28 17:20:11 +00:00
}
#[doc(alias = "gst_buffer_list_get")]
2017-07-28 17:20:11 +00:00
pub fn get(&self, idx: u32) -> Option<&BufferRef> {
unsafe {
let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx);
2017-07-28 17:20:11 +00:00
if ptr.is_null() {
None
} else {
Some(BufferRef::from_ptr(ptr))
}
}
}
#[doc(alias = "gst_buffer_list_get")]
pub fn get_owned(&self, idx: u32) -> Option<Buffer> {
unsafe {
let ptr = ffi::gst_buffer_list_get(self.as_mut_ptr(), idx);
from_glib_none(ptr)
}
}
2021-04-20 13:12:36 +00:00
#[doc(alias = "gst_buffer_list_get_writable")]
#[doc(alias = "get_writable")]
2021-04-20 13:12:36 +00:00
pub fn get_mut(&mut self, idx: u32) -> Option<&mut BufferRef> {
unsafe {
let ptr = ffi::gst_buffer_list_get_writable(self.as_mut_ptr(), idx);
if ptr.is_null() {
None
} else {
Some(BufferRef::from_mut_ptr(ptr))
}
}
}
#[doc(alias = "gst_buffer_list_length")]
2017-07-28 17:20:11 +00:00
pub fn len(&self) -> usize {
unsafe { ffi::gst_buffer_list_length(self.as_mut_ptr()) as usize }
2017-07-28 17:20:11 +00:00
}
#[doc(alias = "gst_buffer_list_calculate_size")]
pub fn calculate_size(&self) -> usize {
unsafe { ffi::gst_buffer_list_calculate_size(self.as_mut_ptr()) as usize }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
2017-08-02 16:40:31 +00:00
pub fn iter(&self) -> Iter {
2017-07-28 17:20:11 +00:00
Iter::new(self)
}
pub fn iter_owned(&self) -> IterOwned {
IterOwned::new(self)
}
#[doc(alias = "gst_buffer_list_foreach")]
pub fn foreach<F: FnMut(&Buffer, u32) -> ControlFlow<(), ()>>(&self, func: F) -> bool {
unsafe extern "C" fn trampoline<F: FnMut(&Buffer, u32) -> ControlFlow<(), ()>>(
buffer: *mut *mut ffi::GstBuffer,
idx: u32,
user_data: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
let func = user_data as *const _ as usize as *mut F;
let res = (*func)(&Buffer::from_glib_borrow(*buffer), idx);
matches!(res, ControlFlow::Continue(_)).into_glib()
}
unsafe {
let func_ptr: &F = &func;
from_glib(ffi::gst_buffer_list_foreach(
self.as_ptr() as *mut _,
Some(trampoline::<F>),
func_ptr as *const _ as usize as *mut _,
))
}
}
#[doc(alias = "gst_buffer_list_foreach")]
pub fn foreach_mut<F: FnMut(Buffer, u32) -> ControlFlow<Option<Buffer>, Option<Buffer>>>(
&mut self,
func: F,
) -> bool {
unsafe extern "C" fn trampoline<
F: FnMut(Buffer, u32) -> ControlFlow<Option<Buffer>, Option<Buffer>>,
>(
buffer: *mut *mut ffi::GstBuffer,
idx: u32,
user_data: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
let func = user_data as *const _ as usize as *mut F;
let res = (*func)(
Buffer::from_glib_full(
ptr::replace(buffer, ptr::null_mut::<ffi::GstBuffer>()) as *mut ffi::GstBuffer
),
idx,
);
let (cont, res_buffer) = match res {
ControlFlow::Continue(res_buffer) => (true, res_buffer),
ControlFlow::Break(res_buffer) => (false, res_buffer),
};
match res_buffer {
None => {
*buffer = ptr::null_mut();
}
Some(new_buffer) => {
*buffer = new_buffer.into_ptr();
}
}
cont.into_glib()
}
unsafe {
let func_ptr: &F = &func;
from_glib(ffi::gst_buffer_list_foreach(
self.as_ptr() as *mut _,
Some(trampoline::<F>),
func_ptr as *const _ as usize as *mut _,
))
}
}
2017-07-28 17:20:11 +00:00
}
impl Default for BufferList {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for BufferList {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
BufferListRef::fmt(self, f)
}
}
impl fmt::Debug for BufferListRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2020-10-27 17:27:16 +00:00
use crate::clock_time::ClockTime;
use crate::utils::Displayable;
2021-04-11 19:39:50 +00:00
let size = self.iter().map(|b| b.size()).sum::<usize>();
2018-07-27 10:36:40 +00:00
let (pts, dts) = self
.get(0)
2021-04-11 19:39:50 +00:00
.map(|b| (b.pts(), b.dts()))
2020-10-27 17:27:16 +00:00
.unwrap_or((ClockTime::NONE, ClockTime::NONE));
f.debug_struct("BufferList")
2018-07-27 10:36:40 +00:00
.field("ptr", unsafe { &self.as_ptr() })
.field("buffers", &self.len())
.field("pts", &pts.display())
.field("dts", &dts.display())
.field("size", &size)
.finish()
}
}
macro_rules! define_iter(
($name:ident, $styp:ty, $get_item:expr) => {
#[derive(Debug)]
pub struct $name<'a> {
list: &'a BufferListRef,
idx: u32,
size: u32,
}
impl<'a> $name<'a> {
fn new(list: &'a BufferListRef) -> $name<'a> {
skip_assert_initialized!();
$name {
list,
idx: 0,
size: list.len() as u32,
}
2017-07-28 17:20:11 +00:00
}
}
impl<'a> Iterator for $name<'a> {
type Item = $styp;
2017-07-28 17:20:11 +00:00
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.size {
return None;
}
2017-07-28 17:20:11 +00:00
2021-04-20 13:12:36 +00:00
let item = $get_item(self.list, self.idx)?;
self.idx += 1;
2017-07-28 17:20:11 +00:00
Some(item)
2017-07-28 17:20:11 +00:00
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.idx == self.size {
return (0, Some(0));
}
let remaining = (self.size - self.idx) as usize;
2017-07-28 17:20:11 +00:00
(remaining, Some(remaining))
}
2017-07-28 17:20:11 +00:00
}
impl<'a> DoubleEndedIterator for $name<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.idx == self.size {
return None;
}
self.size -= 1;
2021-04-20 13:12:36 +00:00
$get_item(self.list, self.size)
2017-07-28 17:20:11 +00:00
}
}
2017-07-28 17:20:11 +00:00
impl<'a> ExactSizeIterator for $name<'a> {}
2017-07-28 17:20:11 +00:00
}
);
define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
list.get(idx)
});
2017-07-28 17:20:11 +00:00
define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
list.get_owned(idx)
});
impl<'a> IntoIterator for &'a BufferListRef {
type IntoIter = Iter<'a>;
type Item = &'a BufferRef;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl std::iter::FromIterator<Buffer> for BufferList {
fn from_iter<T: IntoIterator<Item = Buffer>>(iter: T) -> Self {
assert_initialized_main_thread!();
let iter = iter.into_iter();
let mut list = BufferList::new_sized(iter.size_hint().0);
{
let list = list.get_mut().unwrap();
iter.for_each(|b| list.add(b));
}
list
}
}
impl std::iter::Extend<Buffer> for BufferListRef {
fn extend<T: IntoIterator<Item = Buffer>>(&mut self, iter: T) {
iter.into_iter().for_each(|b| self.add(b));
}
}
#[cfg(test)]
mod tests {
use super::*;
2020-10-27 17:27:16 +00:00
use crate::ClockTime;
#[test]
fn test_foreach() {
crate::init().unwrap();
let mut buffer_list = BufferList::new();
{
let buffer_list = buffer_list.get_mut().unwrap();
let mut buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
buffer.get_mut().unwrap().set_pts(ClockTime::ZERO);
buffer_list.add(buffer);
let mut buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
buffer.get_mut().unwrap().set_pts(ClockTime::SECOND);
buffer_list.add(buffer);
}
let mut res = vec![];
buffer_list.foreach(|buffer, idx| {
2021-04-11 19:39:50 +00:00
res.push((buffer.pts(), idx));
ControlFlow::Continue(())
});
2020-10-27 17:27:16 +00:00
assert_eq!(
res,
&[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)]
);
}
#[test]
fn test_foreach_mut() {
crate::init().unwrap();
let mut buffer_list = BufferList::new();
{
let buffer_list = buffer_list.get_mut().unwrap();
let mut buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
buffer.get_mut().unwrap().set_pts(ClockTime::ZERO);
buffer_list.add(buffer);
let mut buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
buffer.get_mut().unwrap().set_pts(ClockTime::SECOND);
buffer_list.add(buffer);
let mut buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
buffer.get_mut().unwrap().set_pts(2 * ClockTime::SECOND);
buffer_list.add(buffer);
}
let mut res = vec![];
buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| {
2021-04-11 19:39:50 +00:00
res.push((buffer.pts(), idx));
2020-10-27 17:27:16 +00:00
if let Some(ClockTime::ZERO) = buffer.pts() {
ControlFlow::Continue(Some(buffer))
2020-10-27 17:27:16 +00:00
} else if let Some(ClockTime::SECOND) = buffer.pts() {
ControlFlow::Continue(None)
} else {
let mut new_buffer = Buffer::new();
2020-10-27 17:27:16 +00:00
new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND);
ControlFlow::Continue(Some(new_buffer))
}
});
assert_eq!(
res,
&[
2020-10-27 17:27:16 +00:00
(Some(ClockTime::ZERO), 0),
(Some(ClockTime::SECOND), 1),
(Some(2 * ClockTime::SECOND), 1)
]
);
let mut res = vec![];
buffer_list.foreach(|buffer, idx| {
2021-04-11 19:39:50 +00:00
res.push((buffer.pts(), idx));
ControlFlow::Continue(())
});
assert_eq!(
res,
2020-10-27 17:27:16 +00:00
&[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)]
);
}
}